Fix integer overflows when the chunk mesh memory gets past 2 GiB.

This was causing corrupt and missing meshes.
This commit is contained in:
IntegratedQuantum 2023-11-30 00:38:49 +01:00
parent 8d561dfff2
commit 2a46592454
2 changed files with 9 additions and 8 deletions

View File

@ -1209,7 +1209,7 @@ pub fn LargeBuffer(comptime Entry: type) type {
fencedFreeLists: [3]std.ArrayList(SubAllocation), fencedFreeLists: [3]std.ArrayList(SubAllocation),
activeFence: u8, activeFence: u8,
capacity: u31, capacity: u31,
used: u32, used: u31,
binding: c_uint, binding: c_uint,
const Self = @This(); const Self = @This();
@ -1283,11 +1283,12 @@ pub fn LargeBuffer(comptime Entry: type) type {
self.used += size; self.used += size;
return result; return result;
} else { } else {
std.log.info("Resizing internal mesh buffer from {} MiB to {} MiB", .{self.capacity*@sizeOf(Entry) >> 20, (self.capacity*@sizeOf(Entry) >> 20)*2}); std.log.info("Resizing internal mesh buffer from {} MiB to {} MiB", .{@as(usize, self.capacity)*@sizeOf(Entry) >> 20, (@as(usize, self.capacity)*@sizeOf(Entry) >> 20)*2});
const oldBuffer = self.ssbo; const oldBuffer = self.ssbo;
defer oldBuffer.deinit(); defer oldBuffer.deinit();
const oldCapacity = self.capacity; const oldCapacity = self.capacity;
self.createBuffer(self.capacity*2); // TODO: Is there a way to free the old buffer before creating the new one? self.createBuffer(self.capacity*|2); // TODO: Is there a way to free the old buffer before creating the new one?
if(self.capacity == oldCapacity) return error.OutOfMemory;
self.used += self.capacity - oldCapacity; self.used += self.capacity - oldCapacity;
try self.finalFree(.{.start = oldCapacity, .len = self.capacity - oldCapacity}); try self.finalFree(.{.start = oldCapacity, .len = self.capacity - oldCapacity});
@ -1333,7 +1334,7 @@ pub fn LargeBuffer(comptime Entry: type) type {
allocation.* = try self.alloc(@intCast(len)); allocation.* = try self.alloc(@intCast(len));
c.glBindBuffer(c.GL_SHADER_STORAGE_BUFFER, self.ssbo.bufferID); c.glBindBuffer(c.GL_SHADER_STORAGE_BUFFER, self.ssbo.bufferID);
const ptr: [*]Entry = @ptrCast(@alignCast( 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) c.glMapBufferRange(c.GL_SHADER_STORAGE_BUFFER, @as(c_long, allocation.start)*@sizeOf(Entry), @as(c_long, allocation.len)*@sizeOf(Entry), c.GL_MAP_WRITE_BIT | c.GL_MAP_INVALIDATE_RANGE_BIT)
)); ));
return ptr[0..len]; return ptr[0..len];
} }
@ -1353,7 +1354,7 @@ pub fn LargeBuffer(comptime Entry: type) type {
allocation.* = try self.alloc(@intCast(data.len)); allocation.* = try self.alloc(@intCast(data.len));
c.glBindBuffer(c.GL_SHADER_STORAGE_BUFFER, self.ssbo.bufferID); c.glBindBuffer(c.GL_SHADER_STORAGE_BUFFER, self.ssbo.bufferID);
const ptr: [*]Entry = @ptrCast(@alignCast( 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) c.glMapBufferRange(c.GL_SHADER_STORAGE_BUFFER, @as(c_long, allocation.start)*@sizeOf(Entry), @as(c_long, allocation.len)*@sizeOf(Entry), c.GL_MAP_WRITE_BIT | c.GL_MAP_INVALIDATE_RANGE_BIT)
)); ));
@memcpy(ptr, data); @memcpy(ptr, data);
std.debug.assert(c.glUnmapBuffer(c.GL_SHADER_STORAGE_BUFFER) == c.GL_TRUE); std.debug.assert(c.glUnmapBuffer(c.GL_SHADER_STORAGE_BUFFER) == c.GL_TRUE);

View File

@ -43,9 +43,9 @@ fn flawedRender() !void {
try draw.print("Mesh Queue size: {}", .{main.renderer.RenderStructure.updatableList.items.len}, 0, y, 8, .left); try draw.print("Mesh Queue size: {}", .{main.renderer.RenderStructure.updatableList.items.len}, 0, y, 8, .left);
y += 8; y += 8;
{ {
const faceDataSize = @sizeOf(main.chunk.meshing.FaceData); const faceDataSize: usize = @sizeOf(main.chunk.meshing.FaceData);
const size = main.chunk.meshing.faceBuffer.capacity*faceDataSize; const size: usize = main.chunk.meshing.faceBuffer.capacity*faceDataSize;
const used = main.chunk.meshing.faceBuffer.used*faceDataSize; const used: usize = main.chunk.meshing.faceBuffer.used*faceDataSize;
var largestFreeBlock: usize = 0; var largestFreeBlock: usize = 0;
for(main.chunk.meshing.faceBuffer.freeBlocks.items) |freeBlock| { for(main.chunk.meshing.faceBuffer.freeBlocks.items) |freeBlock| {
largestFreeBlock = @max(largestFreeBlock, freeBlock.len); largestFreeBlock = @max(largestFreeBlock, freeBlock.len);