Dynamically indirect

- Indirect engine now only allocates as much memory as it needs
This commit is contained in:
Jozufozu 2022-08-20 20:50:26 -07:00
parent bcaf36c48c
commit ebef176089
3 changed files with 61 additions and 13 deletions

View File

@ -5,6 +5,7 @@ import static org.lwjgl.opengl.GL46.*;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import org.lwjgl.system.Pointer; import org.lwjgl.system.Pointer;
import com.jozufozu.flywheel.backend.memory.FlwMemoryTracker;
import com.jozufozu.flywheel.backend.memory.MemoryBlock; import com.jozufozu.flywheel.backend.memory.MemoryBlock;
public class IndirectBuffers { public class IndirectBuffers {
@ -43,8 +44,11 @@ public class IndirectBuffers {
long batchPtr; long batchPtr;
long drawPtr; long drawPtr;
int maxObjectCount; int maxObjectCount = 0;
int maxDrawCount; int maxDrawCount = 0;
float objectGrowthFactor = 2f;
float drawGrowthFactor = 2f;
IndirectBuffers(long objectStride) { IndirectBuffers(long objectStride) {
this.objectStride = objectStride; this.objectStride = objectStride;
@ -63,10 +67,18 @@ public class IndirectBuffers {
void updateCounts(int objectCount, int drawCount) { void updateCounts(int objectCount, int drawCount) {
if (objectCount > maxObjectCount) { if (objectCount > maxObjectCount) {
createObjectStorage(objectCount); var newObjectCount = maxObjectCount;
while (newObjectCount <= objectCount) {
newObjectCount *= objectGrowthFactor;
}
createObjectStorage(newObjectCount);
} }
if (drawCount > maxDrawCount) { if (drawCount > maxDrawCount) {
createDrawStorage(drawCount); var newDrawCount = maxDrawCount;
while (newDrawCount <= drawCount) {
newDrawCount *= drawGrowthFactor;
}
createDrawStorage(newDrawCount);
} }
final long objectSize = objectStride * objectCount; final long objectSize = objectStride * objectCount;
@ -81,24 +93,62 @@ public class IndirectBuffers {
} }
void createObjectStorage(int objectCount) { void createObjectStorage(int objectCount) {
freeObjectStogare();
var objectSize = objectStride * objectCount; var objectSize = objectStride * objectCount;
var targetSize = INT_SIZE * objectCount; var targetSize = INT_SIZE * objectCount;
glNamedBufferStorage(object, objectSize, PERSISTENT_BITS); if (maxObjectCount > 0) {
glNamedBufferStorage(target, targetSize, GPU_ONLY_BITS); var ptr = buffers.ptr();
glNamedBufferStorage(batch, targetSize, PERSISTENT_BITS); nglCreateBuffers(3, ptr);
int objectNew = MemoryUtil.memGetInt(ptr);
int targetNew = MemoryUtil.memGetInt(ptr + 4);
int batchNew = MemoryUtil.memGetInt(ptr + 8);
glNamedBufferStorage(objectNew, objectSize, PERSISTENT_BITS);
glNamedBufferStorage(targetNew, targetSize, GPU_ONLY_BITS);
glNamedBufferStorage(batchNew, targetSize, PERSISTENT_BITS);
glCopyNamedBufferSubData(object, objectNew, 0, 0, objectStride * maxObjectCount);
glCopyNamedBufferSubData(target, targetNew, 0, 0, INT_SIZE * maxObjectCount);
glCopyNamedBufferSubData(batch, batchNew, 0, 0, INT_SIZE * maxObjectCount);
glDeleteBuffers(object);
glDeleteBuffers(target);
glDeleteBuffers(batch);
object = objectNew;
target = targetNew;
batch = batchNew;
} else {
glNamedBufferStorage(object, objectSize, PERSISTENT_BITS);
glNamedBufferStorage(target, targetSize, GPU_ONLY_BITS);
glNamedBufferStorage(batch, targetSize, PERSISTENT_BITS);
}
objectPtr = nglMapNamedBufferRange(object, 0, objectSize, MAP_BITS); objectPtr = nglMapNamedBufferRange(object, 0, objectSize, MAP_BITS);
batchPtr = nglMapNamedBufferRange(batch, 0, targetSize, MAP_BITS); batchPtr = nglMapNamedBufferRange(batch, 0, targetSize, MAP_BITS);
maxObjectCount = objectCount; maxObjectCount = objectCount;
FlwMemoryTracker._allocGPUMemory(maxObjectCount * objectStride + maxObjectCount * INT_SIZE);
} }
void createDrawStorage(int drawCount) { void createDrawStorage(int drawCount) {
freeDrawStorage();
var drawSize = DRAW_COMMAND_STRIDE * drawCount; var drawSize = DRAW_COMMAND_STRIDE * drawCount;
glNamedBufferStorage(draw, drawSize, SUB_DATA_BITS); glNamedBufferStorage(draw, drawSize, SUB_DATA_BITS);
drawPtr = MemoryUtil.nmemAlloc(drawSize); drawPtr = MemoryUtil.nmemAlloc(drawSize);
// drawPtr = nglMapNamedBufferRange(draw, 0, drawSize, MAP_BITS); // drawPtr = nglMapNamedBufferRange(draw, 0, drawSize, MAP_BITS);
maxDrawCount = drawCount; maxDrawCount = drawCount;
FlwMemoryTracker._allocGPUMemory(maxDrawCount * DRAW_COMMAND_STRIDE);
}
private void freeObjectStogare() {
FlwMemoryTracker._freeGPUMemory(maxObjectCount * objectStride + maxObjectCount * INT_SIZE);
}
private void freeDrawStorage() {
FlwMemoryTracker._freeGPUMemory(maxDrawCount * DRAW_COMMAND_STRIDE);
} }
public void bindAll() { public void bindAll() {
@ -138,5 +188,7 @@ public class IndirectBuffers {
public void delete() { public void delete() {
nglDeleteBuffers(BUFFER_COUNT, buffers.ptr()); nglDeleteBuffers(BUFFER_COUNT, buffers.ptr());
buffers.free(); buffers.free();
freeObjectStogare();
freeDrawStorage();
} }
} }

View File

@ -88,10 +88,6 @@ public class IndirectEngine implements Engine {
RenderSystem.enableCull(); RenderSystem.enableCull();
} }
public void clearAll() {
factories.values().forEach(IndirectFactory::clear);
}
@Override @Override
public void delete() { public void delete() {
factories.values() factories.values()

View File

@ -45,8 +45,8 @@ public class IndirectList<T extends InstancedPart> {
objectStride = storageBufferWriter.getAlignment(); objectStride = storageBufferWriter.getAlignment();
buffers = new IndirectBuffers(objectStride); buffers = new IndirectBuffers(objectStride);
buffers.createBuffers(); buffers.createBuffers();
buffers.createObjectStorage(64 * 64 * 64); buffers.createObjectStorage(128);
buffers.createDrawStorage(64); buffers.createDrawStorage(16);
meshPool = new IndirectMeshPool(vertexType, 1024); meshPool = new IndirectMeshPool(vertexType, 1024);