Misc. tweaks

- Drastically reduce stutter on origin shift (it's still bad)
 - GPUInstancers mark their buffers as dynamic
This commit is contained in:
Jozufozu 2022-06-20 19:26:39 -07:00
parent 1ab1c9e6f6
commit aa10930fa8
6 changed files with 63 additions and 37 deletions

View file

@ -327,12 +327,18 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
AbstractInstance renderer = createRaw(obj); AbstractInstance renderer = createRaw(obj);
if (renderer != null) { if (renderer != null) {
setup(obj, renderer);
instances.put(obj, renderer);
}
return renderer;
}
private void setup(T obj, AbstractInstance renderer) {
renderer.init(); renderer.init();
renderer.updateLight(); renderer.updateLight();
LightUpdater.get(renderer.level) LightUpdater.get(renderer.level)
.addListener(renderer); .addListener(renderer);
instances.put(obj, renderer);
if (renderer instanceof TickableInstance r) { if (renderer instanceof TickableInstance r) {
tickableInstances.put(obj, r); tickableInstances.put(obj, r);
r.tick(); r.tick();
@ -344,14 +350,21 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
} }
} }
return renderer;
}
@Override @Override
public void onOriginShift() { public void onOriginShift() {
ArrayList<T> instanced = new ArrayList<>(instances.keySet()); dynamicInstances.clear();
invalidate(); tickableInstances.clear();
instanced.forEach(this::add); instances.replaceAll((obj, instance) -> {
instance.remove();
AbstractInstance out = createRaw(obj);
if (out != null) {
setup(obj, out);
}
return out;
});
} }
public void detachLightListeners() { public void detachLightListeners() {

View file

@ -3,7 +3,6 @@ package com.jozufozu.flywheel.backend.instancing;
import java.util.List; import java.util.List;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.model.MeshPool;
import com.jozufozu.flywheel.config.FlwCommands; import com.jozufozu.flywheel.config.FlwCommands;
import com.jozufozu.flywheel.config.FlwConfig; import com.jozufozu.flywheel.config.FlwConfig;
import com.jozufozu.flywheel.core.RenderContext; 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.entity.Entity;
import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.event.TickEvent; import net.minecraftforge.event.TickEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
public class InstancedRenderDispatcher { public class InstancedRenderDispatcher {

View file

@ -268,8 +268,8 @@ public class ParallelTaskEngine implements TaskEngine {
} }
public void oneDown() { public void oneDown() {
if (running.decrementAndGet() == 0) {
if (finalizer != null) { if (finalizer != null) {
if (running.decrementAndGet() == 0) {
ParallelTaskEngine.this.syncTasks.add(finalizer); ParallelTaskEngine.this.syncTasks.add(finalizer);
} }
} }

View file

@ -1,23 +1,33 @@
package com.jozufozu.flywheel.backend.instancing.batching; package com.jozufozu.flywheel.backend.instancing.batching;
import java.util.concurrent.atomic.AtomicInteger;
// https://stackoverflow.com/questions/29655531 // https://stackoverflow.com/questions/29655531
public class WaitGroup { public class WaitGroup {
private int jobs = 0; private final AtomicInteger counter = new AtomicInteger(0);
public synchronized void add(int i) { 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() { public synchronized void done() {
if (--jobs == 0) { if (this.counter.decrementAndGet() == 0) {
notifyAll(); this.notifyAll();
} }
} }
public synchronized void await() throws InterruptedException { public synchronized void await() throws InterruptedException {
while (jobs > 0) { while (this.counter.get() > 0) {
wait(); this.wait();
} }
} }

View file

@ -10,6 +10,7 @@ import com.jozufozu.flywheel.api.struct.StructWriter;
import com.jozufozu.flywheel.backend.gl.GlVertexArray; import com.jozufozu.flywheel.backend.gl.GlVertexArray;
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer; import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; 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.MappedBuffer;
import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer; import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
import com.jozufozu.flywheel.backend.instancing.AbstractInstancer; import com.jozufozu.flywheel.backend.instancing.AbstractInstancer;
@ -42,7 +43,7 @@ public class GPUInstancer<D extends InstancedPart> extends AbstractInstancer<D>
public void init() { public void init() {
if (vbo != null) return; if (vbo != null) return;
vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER); vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER, GlBufferUsage.DYNAMIC_DRAW);
vbo.setGrowthMargin(instanceFormat.getStride() * 16); vbo.setGrowthMargin(instanceFormat.getStride() * 16);
} }
@ -53,6 +54,14 @@ public class GPUInstancer<D extends InstancedPart> extends AbstractInstancer<D>
private final Set<GlVertexArray> boundTo = new HashSet<>(); private final Set<GlVertexArray> boundTo = new HashSet<>();
void renderSetup(GlVertexArray vao) { void renderSetup(GlVertexArray vao) {
update();
if (boundTo.add(vao)) {
bindInstanceAttributes(vao);
}
}
private void update() {
if (anyToRemove) { if (anyToRemove) {
removeDeletedInstances(); removeDeletedInstances();
} }
@ -68,10 +77,6 @@ public class GPUInstancer<D extends InstancedPart> extends AbstractInstancer<D>
glInstanceCount = data.size(); glInstanceCount = data.size();
if (boundTo.add(vao)) {
bindInstanceAttributes(vao);
}
anyToRemove = anyToUpdate = false; anyToRemove = anyToUpdate = false;
} }

View file

@ -33,6 +33,7 @@ import com.jozufozu.flywheel.core.compile.ProgramCompiler;
import com.jozufozu.flywheel.core.crumbling.CrumblingProgram; import com.jozufozu.flywheel.core.crumbling.CrumblingProgram;
import com.jozufozu.flywheel.core.model.Mesh; import com.jozufozu.flywheel.core.model.Mesh;
import com.jozufozu.flywheel.core.model.ModelSupplier; 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.shader.WorldProgram;
import com.jozufozu.flywheel.core.source.FileResolution; import com.jozufozu.flywheel.core.source.FileResolution;
import com.jozufozu.flywheel.core.vertex.Formats; import com.jozufozu.flywheel.core.vertex.Formats;
@ -140,6 +141,7 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
type.setupRenderState(); type.setupRenderState();
Textures.bindActiveTextures(); Textures.bindActiveTextures();
CoreShaderInfo coreShaderInfo = CoreShaderInfo.get(); CoreShaderInfo coreShaderInfo = CoreShaderInfo.get();
StateSnapshot state = GameStateRegistry.takeSnapshot();
for (var entry : Multimaps.asMap(multimap).entrySet()) { for (var entry : Multimaps.asMap(multimap).entrySet()) {
var shader = entry.getKey(); var shader = entry.getKey();
@ -151,7 +153,7 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
continue; continue;
} }
setup(shader, coreShaderInfo, camX, camY, camZ, viewProjection, level); setup(shader, coreShaderInfo, camX, camY, camZ, viewProjection, level, state);
for (var drawCall : drawCalls) { for (var drawCall : drawCalls) {
drawCall.render(); drawCall.render();
@ -162,7 +164,7 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
type.clearRenderState(); 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(); VertexType vertexType = desc.vertex();
FileResolution instanceShader = desc.instance() FileResolution instanceShader = desc.instance()
@ -171,7 +173,7 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
P program = context.getProgram(new ProgramCompiler.Context(vertexType, instanceShader, P program = context.getProgram(new ProgramCompiler.Context(vertexType, instanceShader,
material.vertexShader(), material.fragmentShader(), coreShaderInfo.getAdjustedAlphaDiscard(), material.vertexShader(), material.fragmentShader(), coreShaderInfo.getAdjustedAlphaDiscard(),
coreShaderInfo.fogType(), GameStateRegistry.takeSnapshot())); coreShaderInfo.fogType(), ctx));
program.bind(); program.bind();
program.uploadUniforms(camX, camY, camZ, viewProjection, level); program.uploadUniforms(camX, camY, camZ, viewProjection, level);