diff --git a/src/chunk.zig b/src/chunk.zig index 14ac883f..ef814bc3 100644 --- a/src/chunk.zig +++ b/src/chunk.zig @@ -704,8 +704,8 @@ pub const meshing = struct { } offset += neighborLen; } - const fullBuffer = try main.stackAllocator.alloc(FaceData, len); - defer main.stackAllocator.free(fullBuffer); + const fullBuffer = try faceBuffer.allocateAndMapRange(len, &self.bufferAllocation); + defer faceBuffer.unmapRange(fullBuffer); @memcpy(fullBuffer[0..self.coreLen], self.completeList[0..self.coreLen]); var i: usize = self.coreLen; for(0..6) |n| { @@ -713,7 +713,6 @@ pub const meshing = struct { i += list[n].len; } self.vertexCount = @intCast(6*fullBuffer.len); - try faceBuffer.uploadData(fullBuffer, &self.bufferAllocation); // TODO: Avoid the extra copy by writing to the memory-mapped buffer directly. self.wasChanged = true; } diff --git a/src/graphics.zig b/src/graphics.zig index 73eda01c..c2b6d7c7 100644 --- a/src/graphics.zig +++ b/src/graphics.zig @@ -1323,6 +1323,27 @@ pub fn LargeBuffer(comptime Entry: type) type { try self.fencedFreeLists[self.activeFence].append(allocation); } + /// Must unmap after use! + pub fn allocateAndMapRange(self: *Self, len: usize, allocation: *SubAllocation) ![]Entry { + try self.free(allocation.*); + if(len == 0) { + allocation.len = 0; + return &.{}; + } + allocation.* = try self.alloc(@intCast(len)); + c.glBindBuffer(c.GL_SHADER_STORAGE_BUFFER, self.ssbo.bufferID); + const ptr: [*]Entry = @ptrCast(@alignCast( + c.glMapBufferRange(c.GL_SHADER_STORAGE_BUFFER, allocation.start*@sizeOf(Entry), allocation.len*@sizeOf(Entry), c.GL_MAP_WRITE_BIT | c.GL_MAP_INVALIDATE_RANGE_BIT) + )); + return ptr[0..len]; + } + + pub fn unmapRange(self: *Self, range: []Entry) void { + if(range.len == 0) return; + c.glBindBuffer(c.GL_SHADER_STORAGE_BUFFER, self.ssbo.bufferID); + std.debug.assert(c.glUnmapBuffer(c.GL_SHADER_STORAGE_BUFFER) == c.GL_TRUE); + } + pub fn uploadData(self: *Self, data: []Entry, allocation: *SubAllocation) !void { try self.free(allocation.*); if(data.len == 0) {