diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java index 304bac4f0..7a8800bc3 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java @@ -1,9 +1,16 @@ package com.jozufozu.flywheel.backend.instancing; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Objects; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.function.Consumer; import javax.annotation.Nullable; @@ -11,6 +18,7 @@ import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.material.MaterialManager; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArraySet; import net.minecraft.client.renderer.ActiveRenderInfo; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Vector3f; @@ -19,8 +27,8 @@ public abstract class InstanceManager implements MaterialManager.OriginShiftL public final MaterialManager materialManager; - protected final ArrayList queuedAdditions; - protected final ConcurrentHashMap.KeySetView queuedUpdates; + private final Set queuedAdditions; + private final Set queuedUpdates; protected final Map instances; protected final Object2ObjectOpenHashMap tickableInstances; @@ -31,8 +39,8 @@ public abstract class InstanceManager implements MaterialManager.OriginShiftL public InstanceManager(MaterialManager materialManager) { this.materialManager = materialManager; - this.queuedUpdates = ConcurrentHashMap.newKeySet(64); - this.queuedAdditions = new ArrayList<>(64); + this.queuedUpdates = new HashSet<>(64); + this.queuedAdditions = new HashSet<>(64); this.instances = new HashMap<>(); this.dynamicInstances = new Object2ObjectOpenHashMap<>(); @@ -49,6 +57,7 @@ public abstract class InstanceManager implements MaterialManager.OriginShiftL public void tick(double cameraX, double cameraY, double cameraZ) { tick++; + processQueuedUpdates(); // integer camera pos int cX = (int) cameraX; @@ -72,12 +81,6 @@ public abstract class InstanceManager implements MaterialManager.OriginShiftL if ((tick % getUpdateDivisor(dX, dY, dZ)) == 0) instance.tick(); }); } - - queuedUpdates.forEach(te -> { - queuedUpdates.remove(te); - - update(te); - }); } public void beginFrame(ActiveRenderInfo info) { @@ -118,7 +121,9 @@ public abstract class InstanceManager implements MaterialManager.OriginShiftL if (!Backend.getInstance() .canUseInstancing()) return; - queuedAdditions.add(obj); + synchronized (queuedAdditions) { + queuedAdditions.add(obj); + } } public void update(T obj) { @@ -144,8 +149,9 @@ public abstract class InstanceManager implements MaterialManager.OriginShiftL public synchronized void queueUpdate(T obj) { if (!Backend.getInstance() .canUseInstancing()) return; - - queuedUpdates.add(obj); + synchronized (queuedUpdates) { + queuedUpdates.add(obj); + } } public void onLightUpdate(T obj) { @@ -176,7 +182,6 @@ public abstract class InstanceManager implements MaterialManager.OriginShiftL tickableInstances.clear(); } - @SuppressWarnings("unchecked") @Nullable protected IInstance getInstance(I obj, boolean create) { if (!Backend.getInstance() @@ -193,11 +198,30 @@ public abstract class InstanceManager implements MaterialManager.OriginShiftL } } - protected synchronized void processQueuedAdditions() { - if (queuedAdditions.size() > 0) { - queuedAdditions.forEach(this::addInternal); + protected void processQueuedAdditions() { + ArrayList queued; + + synchronized (queuedAdditions) { + queued = new ArrayList<>(queuedAdditions); queuedAdditions.clear(); } + + if (queued.size() > 0) { + queued.forEach(this::addInternal); + } + } + + protected void processQueuedUpdates() { + ArrayList queued; + + synchronized (queuedUpdates) { + queued = new ArrayList<>(queuedUpdates); + queuedUpdates.clear(); + } + + if (queued.size() > 0) { + queued.forEach(this::update); + } } protected boolean shouldFrameUpdate(BlockPos worldPos, float lookX, float lookY, float lookZ, int cX, int cY, int cZ) {