Use task engine/sync to update instances

This commit is contained in:
Jozufozu 2021-12-17 02:17:39 -08:00
parent f651676dea
commit ffe17e4449
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.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -31,11 +32,13 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
protected final Map<T, AbstractInstance> instances;
protected final Object2ObjectOpenHashMap<T, ITickableInstance> tickableInstances;
protected final Object2ObjectOpenHashMap<T, IDynamicInstance> dynamicInstances;
private final TaskEngine taskEngine;
protected int frame;
protected int tick;
public InstanceManager(MaterialManager materialManager) {
public InstanceManager(TaskEngine taskEngine, MaterialManager materialManager) {
this.taskEngine = taskEngine;
this.materialManager = materialManager;
this.queuedUpdates = 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 cZ = (int) cameraZ;
if (tickableInstances.size() > 0) {
tickableInstances.object2ObjectEntrySet().parallelStream().forEach(e -> {
ITickableInstance instance = e.getValue();
if (!instance.decreaseTickRateWithDistance()) {
instance.tick();
return;
ArrayList<ITickableInstance> instances = new ArrayList<>(tickableInstances.values());
int incr = 500;
int size = instances.size();
int start = 0;
while (start < size) {
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) {
frame++;
processQueuedAdditions();
@ -117,14 +134,22 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
int cY = (int) info.getPosition().y;
int cZ = (int) info.getPosition().z;
if (dynamicInstances.size() > 0) {
dynamicInstances.object2ObjectEntrySet()
.parallelStream()
.forEach(e -> {
IDynamicInstance dyn = e.getValue();
if (!dyn.decreaseFramerateWithDistance() || shouldFrameUpdate(dyn.getWorldPosition(), lookX, lookY, lookZ, cX, cY, cZ))
dyn.beginFrame();
});
ArrayList<IDynamicInstance> instances = new ArrayList<>(dynamicInstances.values());
int incr = 500;
int size = instances.size();
int start = 0;
while (start < size) {
int end = Math.min(start + incr, size);
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<BlockEntity> tileEntityInstanceManager;
protected final BatchExecutor executor;
protected final BatchExecutor taskEngine;
public InstanceWorld() {
this.executor = new BatchExecutor();
this.executor.startWorkers();
this.taskEngine = new BatchExecutor();
this.taskEngine.startWorkers();
FlwEngine engine = Backend.getInstance()
.getEngine();
@ -42,19 +42,19 @@ public class InstanceWorld {
switch (engine) {
case GL33 -> {
InstancingEngine<WorldProgram> manager = InstancingEngine.builder(Contexts.WORLD)
.build(this.executor);
.build(this.taskEngine);
entityInstanceManager = new EntityInstanceManager(manager);
tileEntityInstanceManager = new TileInstanceManager(manager);
entityInstanceManager = new EntityInstanceManager(this.taskEngine, manager);
tileEntityInstanceManager = new TileInstanceManager(this.taskEngine, manager);
manager.addListener(entityInstanceManager);
manager.addListener(tileEntityInstanceManager);
this.engine = manager;
}
case BATCHING -> {
this.engine = new BatchingEngine(this.executor);
entityInstanceManager = new EntityInstanceManager(this.engine);
tileEntityInstanceManager = new TileInstanceManager(this.engine);
this.engine = new BatchingEngine(this.taskEngine);
entityInstanceManager = new EntityInstanceManager(this.taskEngine, this.engine);
tileEntityInstanceManager = new TileInstanceManager(this.taskEngine, this.engine);
}
default -> throw new IllegalArgumentException("Unknown engine type");
}
@ -72,7 +72,7 @@ public class InstanceWorld {
* Free all acquired resources and invalidate this instance world.
*/
public void delete() {
this.executor.stopWorkers();
this.taskEngine.stopWorkers();
engine.delete();
entityInstanceManager.detachLightListeners();
tileEntityInstanceManager.detachLightListeners();
@ -89,6 +89,8 @@ public class InstanceWorld {
public void beginFrame(BeginFrameEvent event) {
engine.beginFrame(event.getInfo());
taskEngine.syncPoint();
tileEntityInstanceManager.beginFrame(event.getInfo());
entityInstanceManager.beginFrame(event.getInfo());
}
@ -113,6 +115,7 @@ public class InstanceWorld {
* Draw the given layer.
*/
public void renderLayer(RenderLayerEvent event) {
taskEngine.syncPoint();
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);
taskEngine.syncPoint();
for (Map.Entry<RenderType, BatchedMaterialGroup> entry : layers.get(event.getLayer()).entrySet()) {
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.backend.Backend;
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.InstancedRenderRegistry;
import com.jozufozu.flywheel.backend.instancing.TaskEngine;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.Entity;
@ -13,8 +15,8 @@ import net.minecraft.world.level.Level;
public class EntityInstanceManager extends InstanceManager<Entity> {
public EntityInstanceManager(MaterialManager materialManager) {
super(materialManager);
public EntityInstanceManager(TaskEngine executor, MaterialManager materialManager) {
super(executor, materialManager);
}
@Override

View File

@ -3,8 +3,10 @@ package com.jozufozu.flywheel.backend.instancing.tile;
import com.jozufozu.flywheel.api.MaterialManager;
import com.jozufozu.flywheel.backend.Backend;
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.InstancedRenderRegistry;
import com.jozufozu.flywheel.backend.instancing.TaskEngine;
import net.minecraft.core.BlockPos;
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 TileInstanceManager(MaterialManager materialManager) {
super(materialManager);
public TileInstanceManager(TaskEngine executor, MaterialManager materialManager) {
super(executor, materialManager);
}
@Override

View File

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