🔍 Module Scanned
modules/world-meshing/src/ (automated audit scan)
📝 Summary
The buildSubchunk function in chunk_mesh.zig has an off-by-one error in its Y-axis loop for horizontal (top/bottom) face meshing. The loop condition while (sy <= y1) iterates 17 times instead of 16, causing an extra slice to be generated at the boundary between subchunks. For the topmost subchunk (si=15, y=240-256), this results in querying getLightSafe at y=256, which triggers the known light leak bug (issue #702).
📍 Location
- File:
modules/world-meshing/src/chunk_mesh.zig:142
- Function/Scope:
buildSubchunk
🔴 Severity: High
- High: Memory leaks, race conditions, incorrect rendering, broken features
💥 Impact
When meshing subchunk 15 (the topmost subchunk, Y range 240-255), the loop iterates with sy = 240, 241, ..., 255, 256. The final iteration queries getLightSafe at y=256, which returns MAX_LIGHT (15) due to the bug in getLightSafe at modules/world-core/src/chunk.zig:152. This causes:
- Sky light leakage: Incorrectly bright faces rendered at chunk tops
- Duplicate mesh slices: 17 slices instead of 16 for top faces, wasting GPU bandwidth
- Incorrect face generation: The boundary slice at y=256 queries blocks at y=255 and y=256, but y=256 is outside the world
🔎 Evidence
// Line 137-144 in chunk_mesh.zig
const y0: i32 = @intCast(si * SUBCHUNK_SIZE);
const y1: i32 = y0 + SUBCHUNK_SIZE;
// Mesh horizontal slices (top/bottom faces)
var sy: i32 = y0;
while (sy <= y1) : (sy += 1) { // BUG: should be sy < y1
try greedy_mesher.meshSlice(self.allocator, chunk, neighbors, .top, sy, si, &solid_verts, &cutout_verts, &fluid_verts, atlas);
}
For subchunk 0 (si=0, y0=0, y1=16): loop runs 17 times (sy=0..16) instead of 16.
For subchunk 15 (si=15, y0=240, y1=256): loop runs 17 times (sy=240..256), with sy=256 triggering the getLightSafe bug.
Compare with the correct pattern in flat_quad_mesher.zig:38:
while (y < y1) : (y += 1) { // Correct: only 16 iterations
And the x/z loops in the same function which are intentionally different (chunk boundaries, not subchunk boundaries):
var sx: i32 = 0;
while (sx <= CHUNK_SIZE_X) : (sx += 1) { // Correct: 17 iterations for 16-wide chunk
🛠️ Proposed Fix
Change line 142 in chunk_mesh.zig from:
while (sy <= y1) : (sy += 1) {
to:
while (sy < y1) : (sy += 1) {
This matches the pattern used in all other meshers (flat_quad_mesher.zig, tall_cross_mesher.zig, wall_attached_mesher.zig, cross_mesher.zig) which correctly use < y1.
✅ Acceptance Criteria
📚 References
🔍 Module Scanned
modules/world-meshing/src/(automated audit scan)📝 Summary
The
buildSubchunkfunction inchunk_mesh.zighas an off-by-one error in its Y-axis loop for horizontal (top/bottom) face meshing. The loop conditionwhile (sy <= y1)iterates 17 times instead of 16, causing an extra slice to be generated at the boundary between subchunks. For the topmost subchunk (si=15, y=240-256), this results in queryinggetLightSafeat y=256, which triggers the known light leak bug (issue #702).📍 Location
modules/world-meshing/src/chunk_mesh.zig:142buildSubchunk🔴 Severity: High
💥 Impact
When meshing subchunk 15 (the topmost subchunk, Y range 240-255), the loop iterates with
sy = 240, 241, ..., 255, 256. The final iteration queriesgetLightSafeat y=256, which returns MAX_LIGHT (15) due to the bug ingetLightSafeatmodules/world-core/src/chunk.zig:152. This causes:🔎 Evidence
For subchunk 0 (si=0, y0=0, y1=16): loop runs 17 times (sy=0..16) instead of 16.
For subchunk 15 (si=15, y0=240, y1=256): loop runs 17 times (sy=240..256), with sy=256 triggering the getLightSafe bug.
Compare with the correct pattern in
flat_quad_mesher.zig:38:And the x/z loops in the same function which are intentionally different (chunk boundaries, not subchunk boundaries):
🛠️ Proposed Fix
Change line 142 in
chunk_mesh.zigfrom:to:
This matches the pattern used in all other meshers (
flat_quad_mesher.zig,tall_cross_mesher.zig,wall_attached_mesher.zig,cross_mesher.zig) which correctly use< y1.✅ Acceptance Criteria
zig build testpassgetLightSafewith y >= 256 from the meshing systemnix develop --command zig build test📚 References
modules/world-meshing/src/meshing/boundary.zig