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 4e7452984..5764819c6 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java @@ -327,31 +327,44 @@ public abstract class InstanceManager implements InstancingEngine.OriginShift AbstractInstance renderer = createRaw(obj); if (renderer != null) { - renderer.init(); - renderer.updateLight(); - LightUpdater.get(renderer.level) - .addListener(renderer); + setup(obj, renderer); instances.put(obj, renderer); - - if (renderer instanceof TickableInstance r) { - tickableInstances.put(obj, r); - r.tick(); - } - - if (renderer instanceof DynamicInstance r) { - dynamicInstances.put(obj, r); - r.beginFrame(); - } } return renderer; } + private void setup(T obj, AbstractInstance renderer) { + renderer.init(); + renderer.updateLight(); + LightUpdater.get(renderer.level) + .addListener(renderer); + if (renderer instanceof TickableInstance r) { + tickableInstances.put(obj, r); + r.tick(); + } + + if (renderer instanceof DynamicInstance r) { + dynamicInstances.put(obj, r); + r.beginFrame(); + } + } + @Override public void onOriginShift() { - ArrayList instanced = new ArrayList<>(instances.keySet()); - invalidate(); - instanced.forEach(this::add); + dynamicInstances.clear(); + tickableInstances.clear(); + instances.replaceAll((obj, instance) -> { + instance.remove(); + + AbstractInstance out = createRaw(obj); + + if (out != null) { + setup(obj, out); + } + + return out; + }); } public void detachLightListeners() { diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java index edb4ea4bd..783cf2efe 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java @@ -3,7 +3,6 @@ package com.jozufozu.flywheel.backend.instancing; import java.util.List; import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.backend.model.MeshPool; import com.jozufozu.flywheel.config.FlwCommands; import com.jozufozu.flywheel.config.FlwConfig; import com.jozufozu.flywheel.core.RenderContext; @@ -18,10 +17,7 @@ import net.minecraft.client.renderer.RenderType; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.event.TickEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; public class InstancedRenderDispatcher { diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/ParallelTaskEngine.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/ParallelTaskEngine.java index cea0cbadb..e5928d6f2 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/ParallelTaskEngine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/ParallelTaskEngine.java @@ -268,8 +268,8 @@ public class ParallelTaskEngine implements TaskEngine { } public void oneDown() { - if (running.decrementAndGet() == 0) { - if (finalizer != null) { + if (finalizer != null) { + if (running.decrementAndGet() == 0) { ParallelTaskEngine.this.syncTasks.add(finalizer); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/WaitGroup.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/WaitGroup.java index df7ffb7d9..a27f8cbdc 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/WaitGroup.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/WaitGroup.java @@ -1,23 +1,33 @@ package com.jozufozu.flywheel.backend.instancing.batching; +import java.util.concurrent.atomic.AtomicInteger; + // https://stackoverflow.com/questions/29655531 public class WaitGroup { - private int jobs = 0; + private final AtomicInteger counter = new AtomicInteger(0); public synchronized void add(int i) { - jobs += i; + if (i == 0) { + return; + } + + if (i == 1) { + this.counter.incrementAndGet(); + } else { + this.counter.addAndGet(i); + } } public synchronized void done() { - if (--jobs == 0) { - notifyAll(); + if (this.counter.decrementAndGet() == 0) { + this.notifyAll(); } } public synchronized void await() throws InterruptedException { - while (jobs > 0) { - wait(); + while (this.counter.get() > 0) { + this.wait(); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java index 6623b391c..d1ba46260 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java @@ -10,6 +10,7 @@ import com.jozufozu.flywheel.api.struct.StructWriter; import com.jozufozu.flywheel.backend.gl.GlVertexArray; import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer; import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; +import com.jozufozu.flywheel.backend.gl.buffer.GlBufferUsage; import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer; import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer; import com.jozufozu.flywheel.backend.instancing.AbstractInstancer; @@ -42,7 +43,7 @@ public class GPUInstancer extends AbstractInstancer public void init() { if (vbo != null) return; - vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER); + vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER, GlBufferUsage.DYNAMIC_DRAW); vbo.setGrowthMargin(instanceFormat.getStride() * 16); } @@ -53,6 +54,14 @@ public class GPUInstancer extends AbstractInstancer private final Set boundTo = new HashSet<>(); void renderSetup(GlVertexArray vao) { + update(); + + if (boundTo.add(vao)) { + bindInstanceAttributes(vao); + } + } + + private void update() { if (anyToRemove) { removeDeletedInstances(); } @@ -68,10 +77,6 @@ public class GPUInstancer extends AbstractInstancer glInstanceCount = data.size(); - if (boundTo.add(vao)) { - bindInstanceAttributes(vao); - } - anyToRemove = anyToUpdate = false; } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java index 7c54d27b4..f5b306129 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java @@ -33,6 +33,7 @@ import com.jozufozu.flywheel.core.compile.ProgramCompiler; import com.jozufozu.flywheel.core.crumbling.CrumblingProgram; import com.jozufozu.flywheel.core.model.Mesh; import com.jozufozu.flywheel.core.model.ModelSupplier; +import com.jozufozu.flywheel.core.shader.StateSnapshot; import com.jozufozu.flywheel.core.shader.WorldProgram; import com.jozufozu.flywheel.core.source.FileResolution; import com.jozufozu.flywheel.core.vertex.Formats; @@ -140,6 +141,7 @@ public class InstancingEngine

implements Engine { type.setupRenderState(); Textures.bindActiveTextures(); CoreShaderInfo coreShaderInfo = CoreShaderInfo.get(); + StateSnapshot state = GameStateRegistry.takeSnapshot(); for (var entry : Multimaps.asMap(multimap).entrySet()) { var shader = entry.getKey(); @@ -151,7 +153,7 @@ public class InstancingEngine

implements Engine { continue; } - setup(shader, coreShaderInfo, camX, camY, camZ, viewProjection, level); + setup(shader, coreShaderInfo, camX, camY, camZ, viewProjection, level, state); for (var drawCall : drawCalls) { drawCall.render(); @@ -162,7 +164,7 @@ public class InstancingEngine

implements Engine { type.clearRenderState(); } - protected P setup(ShaderState desc, CoreShaderInfo coreShaderInfo, double camX, double camY, double camZ, Matrix4f viewProjection, ClientLevel level) { + protected P setup(ShaderState desc, CoreShaderInfo coreShaderInfo, double camX, double camY, double camZ, Matrix4f viewProjection, ClientLevel level, StateSnapshot ctx) { VertexType vertexType = desc.vertex(); FileResolution instanceShader = desc.instance() @@ -171,7 +173,7 @@ public class InstancingEngine

implements Engine { P program = context.getProgram(new ProgramCompiler.Context(vertexType, instanceShader, material.vertexShader(), material.fragmentShader(), coreShaderInfo.getAdjustedAlphaDiscard(), - coreShaderInfo.fogType(), GameStateRegistry.takeSnapshot())); + coreShaderInfo.fogType(), ctx)); program.bind(); program.uploadUniforms(camX, camY, camZ, viewProjection, level);