Skip to content

Commit

Permalink
Fix excessively large allocations in chunk meshing
Browse files Browse the repository at this point in the history
The requested capacity was being multiplied by the vertex
stride more than once, which resulted in far too much
memory being allocated.

Cherry-picked from 267f84d
  • Loading branch information
jellysquid3 committed Feb 21, 2025
1 parent 52ac713 commit 876a1c9
Showing 1 changed file with 28 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ public class ChunkMeshBufferBuilder {
private final int initialCapacity;

private ByteBuffer buffer;
private int count;
private int capacity;
private int vertexCount;
private int vertexCapacity;

private int sectionIndex;

public ChunkMeshBufferBuilder(ChunkVertexType vertexType, int initialCapacity) {
Expand All @@ -24,45 +25,49 @@ public ChunkMeshBufferBuilder(ChunkVertexType vertexType, int initialCapacity) {

this.buffer = null;

this.capacity = initialCapacity;
this.vertexCapacity = initialCapacity;
this.initialCapacity = initialCapacity;
}

public void push(ChunkVertexEncoder.Vertex[] vertices, Material material) {
var vertexStart = this.count;
var vertexCount = vertices.length;

if (this.count + vertexCount >= this.capacity) {
this.grow(this.stride * vertexCount);
if (vertices.length != 4) {
throw new IllegalArgumentException("Only quad primitives (with 4 vertices) can be pushed");
}

long ptr = MemoryUtil.memAddress(this.buffer, this.count * this.stride);
this.ensureCapacity(4);

long ptr = MemoryUtil.memAddress(this.buffer, this.vertexCount * this.stride);

for (ChunkVertexEncoder.Vertex vertex : vertices) {
ptr = this.encoder.write(ptr, material, vertex, this.sectionIndex);
}

this.count += vertexCount;
this.vertexCount += 4;
}

private void grow(int len) {
// The new capacity will at least as large as the write it needs to service
int cap = Math.max(this.capacity * 2, this.capacity + len);
private void ensureCapacity(int vertexCount) {
if (this.vertexCount + vertexCount >= this.vertexCapacity) {
this.grow(vertexCount);
}
}

// Update the buffer and capacity now
this.setBufferSize(cap * this.stride);
private void grow(int vertexCount) {
this.reallocate(
// The new capacity will at least twice as large
Math.max(this.vertexCapacity * 2, this.vertexCapacity + vertexCount)
);
}

private void setBufferSize(int capacity) {
this.buffer = MemoryUtil.memRealloc(this.buffer, capacity * this.stride);
this.capacity = capacity;
private void reallocate(int vertexCount) {
this.buffer = MemoryUtil.memRealloc(this.buffer, vertexCount * this.stride);
this.vertexCapacity = vertexCount;
}

public void start(int sectionIndex) {
this.count = 0;
this.vertexCount = 0;
this.sectionIndex = sectionIndex;

this.setBufferSize(this.initialCapacity);
this.reallocate(this.initialCapacity);
}

public void destroy() {
Expand All @@ -74,18 +79,18 @@ public void destroy() {
}

public boolean isEmpty() {
return this.count == 0;
return this.vertexCount == 0;
}

public ByteBuffer slice() {
if (this.isEmpty()) {
throw new IllegalStateException("No vertex data in buffer");
}

return MemoryUtil.memSlice(this.buffer, 0, this.stride * this.count);
return MemoryUtil.memSlice(this.buffer, 0, this.stride * this.vertexCount);
}

public int count() {
return this.count;
return this.vertexCount;
}
}

0 comments on commit 876a1c9

Please sign in to comment.