commit ac731f2

shrub  ·  2026-08-12 17:04:07 +0000 UTC
parent f31e894
allocate chunk sections on demand to reduce memory usage significantly
5 files changed,  +36, -12
+3, -3
 1@@ -23,9 +23,9 @@ typedef struct {
 2 	i32 x;
 3 	i32 z;
 4 
 5-	ChunkSection sections[CHUNK_SECTION_COUNT];
 6-	u16          section_mask;
 7-	i8           used;
 8+	ChunkSection* sections[CHUNK_SECTION_COUNT];
 9+	u16           section_mask;
10+	i8            used;
11 } Chunk;
12 
13 /* clear chunk contents and mark unused */
+18, -3
 1@@ -1,3 +1,4 @@
 2+#include <stdlib.h>
 3 #include <string.h>
 4 
 5 #include "types.h"
 6@@ -73,7 +74,7 @@ static ChunkSection* world_chunk_section_find(ClientWorld* world, i32 x, i32 z,
 7 	if (!chunk || !(chunk->section_mask & (1U << section)))
 8 		return NULL;
 9 
10-	return &chunk->sections[section];
11+	return chunk->sections[section];
12 }
13 
14 /* rebuild chunk section mesh with face culling
15@@ -89,7 +90,10 @@ static i8 world_chunk_section_mesh_create(ClientWorld* world, Chunk* chunk, i32
16 		                                            section + neighbour_offsets[face][1]);
17 	}
18 
19-	return chunk_section_mesh_create(&chunk->sections[section], neighbours);
20+	if (!chunk->sections[section])
21+		return 0;
22+
23+	return chunk_section_mesh_create(chunk->sections[section], neighbours);
24 }
25 
26 /* rebuild chunk mesh and neighbouring chunk meshes for sections in section_mask
27@@ -191,6 +195,7 @@ i8 world_mesh_create(ClientWorld* world)
28 i8 world_update_chunk(ClientWorld* world, const MCChunkUpdate* update, const u8* data)
29 {
30 	Chunk* chunk;
31+	ChunkSection* chunk_section;
32 	i32    section;
33 	i32    data_section;
34 	u16    remesh_mask;
35@@ -215,8 +220,18 @@ i8 world_update_chunk(ClientWorld* world, const MCChunkUpdate* update, const u8*
36 		if (!(update->mask & (1U << section)))
37 			continue;
38 
39+		chunk_section = chunk->sections[section];
40+		if (!chunk_section) {
41+			chunk_section = calloc(1, sizeof(*chunk_section));
42+			if (!chunk_section) {
43+				mg_log(LOG_ERR, "Failed to allocate chunk section");
44+				return 0;
45+			}
46+			chunk->sections[section] = chunk_section;
47+		}
48+
49 		/* decode section data into mesh */
50-		if (!chunk_section_decode(&chunk->sections[section],
51+		if (!chunk_section_decode(chunk_section,
52 		                          data + (size_t)data_section * MC_CHUNK_SECTION_BLOCK_BYTES,
53 		                          MC_CHUNK_SECTION_BLOCK_BYTES)) {
54 			mg_log(LOG_ERR, "Failed to create chunk mesh");
+7, -2
 1@@ -55,7 +55,10 @@ static void create_local_world(void)
 2 		chunk->used = 1;
 3 		chunk->x = x;
 4 		chunk->z = z;
 5-		chunk_section_create(&chunk->sections[0]);
 6+		chunk->sections[0] = calloc(1, sizeof(*chunk->sections[0]));
 7+		if (!chunk->sections[0])
 8+			mg_die(MG_EC_MESH_CREATE, "Failed to allocate local chunk section");
 9+		chunk_section_create(chunk->sections[0]);
10 		chunk->section_mask = 1;
11 	}
12 
13@@ -309,7 +312,9 @@ static void render_world(void)
14 			if (!(chunk->section_mask & (1U << section_index)))
15 				continue;
16 
17-			section = &chunk->sections[section_index];
18+			section = chunk->sections[section_index];
19+			if (!section)
20+				continue;
21 			model = MG_Translate(MG_V3(chunk->x * CHUNK_WIDTH, section_index * CHUNK_SECTION_HEIGHT,
22 			                           chunk->z * CHUNK_DEPTH));
23 			mvp = MG_MulM4(proj, MG_MulM4(view, model));
+2, -2
 1@@ -13,8 +13,8 @@
 2 
 3 #define MAX_MESHES (16384)
 4 #define MAX_TEXTURES (512)
 5-#define S3L_MAX_WIDTH (4096)
 6-#define S3L_MAX_HEIGHT (4096)
 7+#define S3L_MAX_WIDTH (800)
 8+#define S3L_MAX_HEIGHT (600)
 9 #define SOFTWARE_MAX_WIDTH (800)
10 #define SOFTWARE_MAX_HEIGHT (600)
11 #define TEXTURE_SAMPLE_PERIOD (4)
+6, -2
 1@@ -75,8 +75,12 @@ void chunk_clear(Chunk* chunk)
 2 		return;
 3 
 4 	for (section = 0; section < CHUNK_SECTION_COUNT; section++) {
 5-		chunk_section_mesh_destroy(&chunk->sections[section]);
 6-		memset(&chunk->sections[section], 0, sizeof(chunk->sections[section]));
 7+		if (!chunk->sections[section])
 8+			continue;
 9+
10+		chunk_section_mesh_destroy(chunk->sections[section]);
11+		free(chunk->sections[section]);
12+		chunk->sections[section] = NULL;
13 	}
14 
15 	chunk->section_mask = 0;