DeDelleetete

- Process instancer deletions in parallel
- Give DrawManagers a frame plan
This commit is contained in:
Jozufozu 2024-09-28 14:26:15 -07:00
parent 7bd59f7b14
commit 48fdcdb751
7 changed files with 16 additions and 19 deletions

View file

@ -160,7 +160,7 @@ public abstract class AbstractInstancer<I extends Instance> implements Instancer
deleted.set(index);
}
protected void removeDeletedInstances() {
public void removeDeletedInstances() {
if (deleted.isEmpty()) {
return;
}

View file

@ -10,14 +10,17 @@ import java.util.concurrent.ConcurrentLinkedQueue;
import com.mojang.datafixers.util.Pair;
import dev.engine_room.flywheel.api.RenderContext;
import dev.engine_room.flywheel.api.backend.Engine;
import dev.engine_room.flywheel.api.instance.Instance;
import dev.engine_room.flywheel.api.instance.InstanceType;
import dev.engine_room.flywheel.api.model.Model;
import dev.engine_room.flywheel.api.task.Plan;
import dev.engine_room.flywheel.api.visualization.VisualType;
import dev.engine_room.flywheel.backend.FlwBackend;
import dev.engine_room.flywheel.backend.engine.embed.Environment;
import dev.engine_room.flywheel.backend.engine.embed.EnvironmentStorage;
import dev.engine_room.flywheel.lib.task.ForEachPlan;
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import net.minecraft.client.resources.model.ModelBakery;
@ -45,6 +48,11 @@ public abstract class DrawManager<N extends AbstractInstancer<?>> {
return (AbstractInstancer<I>) instancers.computeIfAbsent(key, this::createAndDeferInit);
}
public Plan<RenderContext> createFramePlan() {
// Go wide on instancers to process deletions in parallel.
return ForEachPlan.of(() -> new ArrayList<>(instancers.values()), AbstractInstancer::removeDeletedInstances);
}
public void flush(LightStorage lightStorage, EnvironmentStorage environmentStorage) {
// Thread safety: flush is called from the render thread after all visual updates have been made,
// so there are no:tm: threads we could be racing with.

View file

@ -50,7 +50,8 @@ public class EngineImpl implements Engine {
@Override
public Plan<RenderContext> createFramePlan() {
return lightStorage.createFramePlan();
return drawManager.createFramePlan()
.and(lightStorage.createFramePlan());
}
@Override

View file

@ -64,7 +64,6 @@ public class IndirectCullingGroup<I extends Instance> {
int modelIndex = 0;
for (var iterator = instancers.iterator(); iterator.hasNext(); ) {
var instancer = iterator.next();
instancer.update();
var instanceCount = instancer.instanceCount();
if (instanceCount == 0) {
@ -73,7 +72,7 @@ public class IndirectCullingGroup<I extends Instance> {
continue;
}
instancer.postUpdate(modelIndex, instanceCountThisFrame);
instancer.update(modelIndex, instanceCountThisFrame);
instanceCountThisFrame += instanceCount;
modelIndex++;
@ -172,7 +171,7 @@ public class IndirectCullingGroup<I extends Instance> {
public void add(IndirectInstancer<I> instancer, InstancerKey<I> key, MeshPool meshPool) {
instancer.mapping = buffers.objectStorage.createMapping();
instancer.postUpdate(instancers.size(), -1);
instancer.update(instancers.size(), -1);
instancers.add(instancer);

View file

@ -55,11 +55,7 @@ public class IndirectInstancer<I extends Instance> extends AbstractInstancer<I>
return associatedDraws;
}
public void update() {
removeDeletedInstances();
}
public void postUpdate(int modelIndex, int baseInstance) {
public void update(int modelIndex, int baseInstance) {
this.modelIndex = modelIndex;
this.baseInstance = baseInstance;
mapping.update(modelIndex, instanceCount());

View file

@ -65,13 +65,11 @@ public class InstancedDrawManager extends DrawManager<InstancedInstancer<?>> {
this.instancers.values()
.removeIf(instancer -> {
// Update the instancers and remove any that are empty.
instancer.update();
if (instancer.instanceCount() == 0) {
instancer.delete();
return true;
} else {
instancer.updateBuffer();
return false;
}
});

View file

@ -44,12 +44,7 @@ public class InstancedInstancer<I extends Instance> extends AbstractInstancer<I>
vbo = new GlBuffer(GlBufferUsage.DYNAMIC_DRAW);
}
public void update() {
removeDeletedInstances();
updateBuffer();
}
private void updateBuffer() {
public void updateBuffer() {
if (changed.isEmpty() || vbo == null) {
return;
}