Use task engine/sync to update instances

This commit is contained in:
Jozufozu 2021-12-17 02:17:39 -08:00
parent 80b3c1ed35
commit 54703d8c1a
6 changed files with 71 additions and 40 deletions

View file

@ -3,6 +3,7 @@ package com.jozufozu.flywheel.backend.instancing;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -31,11 +32,13 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
protected final Map<T, AbstractInstance> instances; protected final Map<T, AbstractInstance> instances;
protected final Object2ObjectOpenHashMap<T, ITickableInstance> tickableInstances; protected final Object2ObjectOpenHashMap<T, ITickableInstance> tickableInstances;
protected final Object2ObjectOpenHashMap<T, IDynamicInstance> dynamicInstances; protected final Object2ObjectOpenHashMap<T, IDynamicInstance> dynamicInstances;
private final TaskEngine taskEngine;
protected int frame; protected int frame;
protected int tick; protected int tick;
public InstanceManager(MaterialManager materialManager) { public InstanceManager(TaskEngine taskEngine, MaterialManager materialManager) {
this.taskEngine = taskEngine;
this.materialManager = materialManager; this.materialManager = materialManager;
this.queuedUpdates = new HashSet<>(64); this.queuedUpdates = new HashSet<>(64);
this.queuedAdditions = new HashSet<>(64); this.queuedAdditions = new HashSet<>(64);
@ -84,25 +87,39 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
int cY = (int) cameraY; int cY = (int) cameraY;
int cZ = (int) cameraZ; int cZ = (int) cameraZ;
if (tickableInstances.size() > 0) { ArrayList<ITickableInstance> instances = new ArrayList<>(tickableInstances.values());
tickableInstances.object2ObjectEntrySet().parallelStream().forEach(e -> { int incr = 500;
ITickableInstance instance = e.getValue(); int size = instances.size();
if (!instance.decreaseTickRateWithDistance()) { int start = 0;
instance.tick(); while (start < size) {
return; int end = Math.min(start + incr, size);
List<ITickableInstance> sub = instances.subList(start, end);
taskEngine.submit(() -> {
for (ITickableInstance instance : sub) {
tickInstance(cX, cY, cZ, instance);
} }
BlockPos pos = instance.getWorldPosition();
int dX = pos.getX() - cX;
int dY = pos.getY() - cY;
int dZ = pos.getZ() - cZ;
if ((tick % getUpdateDivisor(dX, dY, dZ)) == 0) instance.tick();
}); });
start += incr;
} }
} }
private void tickInstance(int cX, int cY, int cZ, ITickableInstance instance) {
if (!instance.decreaseTickRateWithDistance()) {
instance.tick();
return;
}
BlockPos pos = instance.getWorldPosition();
int dX = pos.getX() - cX;
int dY = pos.getY() - cY;
int dZ = pos.getZ() - cZ;
if ((tick % getUpdateDivisor(dX, dY, dZ)) == 0) instance.tick();
}
public void beginFrame(Camera info) { public void beginFrame(Camera info) {
frame++; frame++;
processQueuedAdditions(); processQueuedAdditions();
@ -117,14 +134,22 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
int cY = (int) info.getPosition().y; int cY = (int) info.getPosition().y;
int cZ = (int) info.getPosition().z; int cZ = (int) info.getPosition().z;
if (dynamicInstances.size() > 0) { ArrayList<IDynamicInstance> instances = new ArrayList<>(dynamicInstances.values());
dynamicInstances.object2ObjectEntrySet() int incr = 500;
.parallelStream() int size = instances.size();
.forEach(e -> { int start = 0;
IDynamicInstance dyn = e.getValue(); while (start < size) {
if (!dyn.decreaseFramerateWithDistance() || shouldFrameUpdate(dyn.getWorldPosition(), lookX, lookY, lookZ, cX, cY, cZ)) int end = Math.min(start + incr, size);
dyn.beginFrame();
}); List<IDynamicInstance> sub = instances.subList(start, end);
taskEngine.submit(() -> {
for (IDynamicInstance dyn : sub) {
if (!dyn.decreaseFramerateWithDistance() || shouldFrameUpdate(dyn.getWorldPosition(), lookX, lookY, lookZ, cX, cY, cZ))
dyn.beginFrame();
}
});
start += incr;
} }
} }

View file

@ -29,12 +29,12 @@ public class InstanceWorld {
protected final InstanceManager<Entity> entityInstanceManager; protected final InstanceManager<Entity> entityInstanceManager;
protected final InstanceManager<BlockEntity> tileEntityInstanceManager; protected final InstanceManager<BlockEntity> tileEntityInstanceManager;
protected final BatchExecutor executor; protected final BatchExecutor taskEngine;
public InstanceWorld() { public InstanceWorld() {
this.executor = new BatchExecutor(); this.taskEngine = new BatchExecutor();
this.executor.startWorkers(); this.taskEngine.startWorkers();
FlwEngine engine = Backend.getInstance() FlwEngine engine = Backend.getInstance()
.getEngine(); .getEngine();
@ -42,19 +42,19 @@ public class InstanceWorld {
switch (engine) { switch (engine) {
case GL33 -> { case GL33 -> {
InstancingEngine<WorldProgram> manager = InstancingEngine.builder(Contexts.WORLD) InstancingEngine<WorldProgram> manager = InstancingEngine.builder(Contexts.WORLD)
.build(this.executor); .build(this.taskEngine);
entityInstanceManager = new EntityInstanceManager(manager); entityInstanceManager = new EntityInstanceManager(this.taskEngine, manager);
tileEntityInstanceManager = new TileInstanceManager(manager); tileEntityInstanceManager = new TileInstanceManager(this.taskEngine, manager);
manager.addListener(entityInstanceManager); manager.addListener(entityInstanceManager);
manager.addListener(tileEntityInstanceManager); manager.addListener(tileEntityInstanceManager);
this.engine = manager; this.engine = manager;
} }
case BATCHING -> { case BATCHING -> {
this.engine = new BatchingEngine(this.executor); this.engine = new BatchingEngine(this.taskEngine);
entityInstanceManager = new EntityInstanceManager(this.engine); entityInstanceManager = new EntityInstanceManager(this.taskEngine, this.engine);
tileEntityInstanceManager = new TileInstanceManager(this.engine); tileEntityInstanceManager = new TileInstanceManager(this.taskEngine, this.engine);
} }
default -> throw new IllegalArgumentException("Unknown engine type"); default -> throw new IllegalArgumentException("Unknown engine type");
} }
@ -72,7 +72,7 @@ public class InstanceWorld {
* Free all acquired resources and invalidate this instance world. * Free all acquired resources and invalidate this instance world.
*/ */
public void delete() { public void delete() {
this.executor.stopWorkers(); this.taskEngine.stopWorkers();
engine.delete(); engine.delete();
entityInstanceManager.detachLightListeners(); entityInstanceManager.detachLightListeners();
tileEntityInstanceManager.detachLightListeners(); tileEntityInstanceManager.detachLightListeners();
@ -89,6 +89,8 @@ public class InstanceWorld {
public void beginFrame(BeginFrameEvent event) { public void beginFrame(BeginFrameEvent event) {
engine.beginFrame(event.getInfo()); engine.beginFrame(event.getInfo());
taskEngine.syncPoint();
tileEntityInstanceManager.beginFrame(event.getInfo()); tileEntityInstanceManager.beginFrame(event.getInfo());
entityInstanceManager.beginFrame(event.getInfo()); entityInstanceManager.beginFrame(event.getInfo());
} }
@ -113,6 +115,7 @@ public class InstanceWorld {
* Draw the given layer. * Draw the given layer.
*/ */
public void renderLayer(RenderLayerEvent event) { public void renderLayer(RenderLayerEvent event) {
taskEngine.syncPoint();
engine.render(event, event.buffers.bufferSource()); engine.render(event, event.buffers.bufferSource());
} }

View file

@ -49,8 +49,6 @@ public class BatchingEngine implements Engine {
stack.translate(-event.camX, -event.camY, -event.camZ); stack.translate(-event.camX, -event.camY, -event.camZ);
taskEngine.syncPoint();
for (Map.Entry<RenderType, BatchedMaterialGroup> entry : layers.get(event.getLayer()).entrySet()) { for (Map.Entry<RenderType, BatchedMaterialGroup> entry : layers.get(event.getLayer()).entrySet()) {
BatchedMaterialGroup group = entry.getValue(); BatchedMaterialGroup group = entry.getValue();

View file

@ -3,8 +3,10 @@ package com.jozufozu.flywheel.backend.instancing.entity;
import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.api.MaterialManager;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.instancing.AbstractInstance; import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
import com.jozufozu.flywheel.backend.instancing.BatchExecutor;
import com.jozufozu.flywheel.backend.instancing.InstanceManager; import com.jozufozu.flywheel.backend.instancing.InstanceManager;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry; import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry;
import com.jozufozu.flywheel.backend.instancing.TaskEngine;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
@ -13,8 +15,8 @@ import net.minecraft.world.level.Level;
public class EntityInstanceManager extends InstanceManager<Entity> { public class EntityInstanceManager extends InstanceManager<Entity> {
public EntityInstanceManager(MaterialManager materialManager) { public EntityInstanceManager(TaskEngine executor, MaterialManager materialManager) {
super(materialManager); super(executor, materialManager);
} }
@Override @Override

View file

@ -3,8 +3,10 @@ package com.jozufozu.flywheel.backend.instancing.tile;
import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.api.MaterialManager;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.instancing.AbstractInstance; import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
import com.jozufozu.flywheel.backend.instancing.BatchExecutor;
import com.jozufozu.flywheel.backend.instancing.InstanceManager; import com.jozufozu.flywheel.backend.instancing.InstanceManager;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry; import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry;
import com.jozufozu.flywheel.backend.instancing.TaskEngine;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.BlockGetter;
@ -13,8 +15,8 @@ import net.minecraft.world.level.block.entity.BlockEntity;
public class TileInstanceManager extends InstanceManager<BlockEntity> { public class TileInstanceManager extends InstanceManager<BlockEntity> {
public TileInstanceManager(MaterialManager materialManager) { public TileInstanceManager(TaskEngine executor, MaterialManager materialManager) {
super(materialManager); super(executor, materialManager);
} }
@Override @Override

View file

@ -1,6 +1,7 @@
package com.jozufozu.flywheel.core.crumbling; package com.jozufozu.flywheel.core.crumbling;
import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.api.MaterialManager;
import com.jozufozu.flywheel.backend.instancing.ImmediateExecutor;
import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager; import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@ -8,7 +9,7 @@ import net.minecraft.core.BlockPos;
public class CrumblingInstanceManager extends TileInstanceManager { public class CrumblingInstanceManager extends TileInstanceManager {
public CrumblingInstanceManager(MaterialManager materialManager) { public CrumblingInstanceManager(MaterialManager materialManager) {
super(materialManager); super(ImmediateExecutor.INSTANCE, materialManager);
} }
@Override @Override