BatchingDrawManager

- Merge BatchLists, BatchedModel, and some parts of BatchingEngine into
BatchingDrawManager for consistency with instancing code
- Have InstancingEngine accept the max origin distance as a constructor
parameter
- Rename TransformSet to TransformCall
This commit is contained in:
PepperCode1 2022-08-19 17:24:13 -07:00
parent 2fe69350ef
commit ba30aca869
12 changed files with 204 additions and 177 deletions

View file

@ -37,7 +37,7 @@ public class InstanceWorld implements AutoCloseable {
public static InstanceWorld create(LevelAccessor level) { public static InstanceWorld create(LevelAccessor level) {
var engine = switch (Backend.getBackendType()) { var engine = switch (Backend.getBackendType()) {
case INSTANCING -> new InstancingEngine(Components.WORLD); case INSTANCING -> new InstancingEngine(Components.WORLD, 100 * 100);
case BATCHING -> new BatchingEngine(); case BATCHING -> new BatchingEngine();
case OFF -> throw new IllegalStateException("Cannot create instance world when backend is off."); case OFF -> throw new IllegalStateException("Cannot create instance world when backend is off.");
}; };

View file

@ -7,6 +7,8 @@ import net.minecraft.client.Camera;
public interface RenderDispatcher { public interface RenderDispatcher {
void beginFrame(TaskEngine taskEngine, RenderContext context);
void renderStage(TaskEngine taskEngine, RenderContext context, RenderStage stage); void renderStage(TaskEngine taskEngine, RenderContext context, RenderStage stage);
/** /**
@ -16,7 +18,5 @@ public interface RenderDispatcher {
*/ */
boolean maintainOriginCoordinate(Camera camera); boolean maintainOriginCoordinate(Camera camera);
void beginFrame(TaskEngine taskEngine, RenderContext context);
void delete(); void delete();
} }

View file

@ -1,14 +0,0 @@
package com.jozufozu.flywheel.backend.instancing.batching;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import net.minecraft.client.renderer.RenderType;
public class BatchLists {
public final Multimap<RenderType, TransformSet<?>> renderLists = ArrayListMultimap.create();
public void add(TransformSet<?> set) {
renderLists.put(set.getMaterial().getBatchingRenderType(), set);
}
}

View file

@ -1,46 +0,0 @@
package com.jozufozu.flywheel.backend.instancing.batching;
import java.util.List;
import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.core.model.Model;
public class BatchedModel<D extends InstancedPart> {
private final StructType<D> type;
private final Model model;
private final CPUInstancer<D> instancer;
private List<TransformSet<D>> layers;
public BatchedModel(StructType<D> type, Model model) {
this.type = type;
this.model = model;
this.instancer = new CPUInstancer<>(type);
}
public void init(BatchLists batchLists) {
layers = model.getMeshes()
.entrySet()
.stream()
.map(entry -> new TransformSet<>(instancer, entry.getKey(), entry.getValue()))
.toList();
for (TransformSet<D> layer : layers) {
batchLists.add(layer);
}
}
public Model getModel() {
return model;
}
public CPUInstancer<D> getInstancer() {
return instancer;
}
public void clear() {
instancer.clear();
}
}

View file

@ -0,0 +1,98 @@
package com.jozufozu.flywheel.backend.instancing.batching;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.jetbrains.annotations.NotNull;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ListMultimap;
import com.jozufozu.flywheel.api.RenderStage;
import com.jozufozu.flywheel.core.model.Model;
import net.minecraft.client.renderer.RenderType;
public class BatchingDrawManager {
private final List<UninitializedModel> uninitializedModels = new ArrayList<>();
private final List<CPUInstancer<?>> allInstancers = new ArrayList<>();
public final Map<RenderStage, TransformSet> renderLists = new EnumMap<>(RenderStage.class);
public final BatchDrawingTracker batchTracker = new BatchDrawingTracker();
public TransformSet get(RenderStage stage) {
return renderLists.getOrDefault(stage, TransformSet.EMPTY);
}
public void create(CPUInstancer<?> instancer, Model model) {
uninitializedModels.add(new UninitializedModel(instancer, model));
}
public void flush() {
for (var model : uninitializedModels) {
add(model.instancer(), model.model());
}
uninitializedModels.clear();
}
public void delete() {
allInstancers.forEach(CPUInstancer::delete);
allInstancers.clear();
}
public void clearInstancers() {
allInstancers.forEach(CPUInstancer::clear);
}
private void add(CPUInstancer<?> instancer, Model model) {
var meshes = model.getMeshes();
for (var entry : meshes.entrySet()) {
TransformCall<?> transformCall = new TransformCall<>(instancer, entry.getKey(), entry.getValue());
var material = transformCall.getMaterial();
var renderType = material.getBatchingRenderType();
// renderLists.computeIfAbsent(material.getRenderStage(), TransformSet::new)
renderLists.computeIfAbsent(RenderStage.AFTER_FINAL_END_BATCH, TransformSet::new)
.put(renderType, transformCall);
}
allInstancers.add(instancer);
}
public static class TransformSet implements Iterable<Map.Entry<RenderType, Collection<TransformCall<?>>>> {
public static final TransformSet EMPTY = new TransformSet(ImmutableListMultimap.of());
final ListMultimap<RenderType, TransformCall<?>> transformCalls;
public TransformSet(RenderStage renderStage) {
transformCalls = ArrayListMultimap.create();
}
public TransformSet(ListMultimap<RenderType, TransformCall<?>> transformCalls) {
this.transformCalls = transformCalls;
}
public void put(RenderType shaderState, TransformCall<?> transformCall) {
transformCalls.put(shaderState, transformCall);
}
public boolean isEmpty() {
return transformCalls.isEmpty();
}
@NotNull
@Override
public Iterator<Map.Entry<RenderType, Collection<TransformCall<?>>>> iterator() {
return transformCalls.asMap()
.entrySet()
.iterator();
}
}
private record UninitializedModel(CPUInstancer<?> instancer, Model model) {
}
}

View file

@ -1,10 +1,11 @@
package com.jozufozu.flywheel.backend.instancing.batching; package com.jozufozu.flywheel.backend.instancing.batching;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.jetbrains.annotations.NotNull;
import com.jozufozu.flywheel.api.RenderStage; import com.jozufozu.flywheel.api.RenderStage;
import com.jozufozu.flywheel.api.instancer.InstancedPart; import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructType;
@ -23,36 +24,44 @@ import net.minecraft.world.phys.Vec3;
public class BatchingEngine implements Engine { public class BatchingEngine implements Engine {
private final Map<StructType<?>, CPUInstancerFactory<?>> factories = new HashMap<>(); protected final BatchingDrawManager drawManager = new BatchingDrawManager();
private final BatchDrawingTracker batchTracker = new BatchDrawingTracker(); protected final Map<StructType<?>, CPUInstancerFactory<?>> factories = new HashMap<>();
private final BatchLists batchLists = new BatchLists();
protected final List<BatchedModel<?>> uninitializedModels = new ArrayList<>();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@NotNull
@Override @Override
public <D extends InstancedPart> CPUInstancerFactory<D> factory(StructType<D> type) { public <D extends InstancedPart> CPUInstancerFactory<D> factory(StructType<D> type) {
return (CPUInstancerFactory<D>) factories.computeIfAbsent(type, this::createFactory); return (CPUInstancerFactory<D>) factories.computeIfAbsent(type, this::createFactory);
} }
public <D extends InstancedPart> CPUInstancerFactory<D> createFactory(StructType<D> type) { @NotNull
return new CPUInstancerFactory<>(type, uninitializedModels::add); private <D extends InstancedPart> CPUInstancerFactory<D> createFactory(StructType<D> type) {
return new CPUInstancerFactory<>(type, drawManager::create);
} }
@Override @Override
public Vec3i getOriginCoordinate() { public void beginFrame(TaskEngine taskEngine, RenderContext context) {
return BlockPos.ZERO; drawManager.flush();
Vec3 cameraPos = context.camera().getPosition();
var stack = FlwUtil.copyPoseStack(context.stack());
stack.translate(-cameraPos.x, -cameraPos.y, -cameraPos.z);
submitTasks(taskEngine, stack, context.level());
} }
public void submitTasks(TaskEngine taskEngine, PoseStack stack, ClientLevel level) { public void submitTasks(TaskEngine taskEngine, PoseStack stack, ClientLevel level) {
batchLists.renderLists.asMap().forEach((renderType, renderList) -> { BatchingDrawManager.TransformSet drawSet = drawManager.get(RenderStage.AFTER_FINAL_END_BATCH);
for (var entry : drawSet) {
var renderType = entry.getKey();
var renderList = entry.getValue();
int vertices = 0; int vertices = 0;
for (var transformSet : renderList) { for (var transformSet : renderList) {
vertices += transformSet.getTotalVertexCount(); vertices += transformSet.getTotalVertexCount();
} }
DrawBuffer buffer = batchTracker.getBuffer(renderType); DrawBuffer buffer = drawManager.batchTracker.getBuffer(renderType);
buffer.prepare(vertices); buffer.prepare(vertices);
int startVertex = 0; int startVertex = 0;
@ -60,7 +69,7 @@ public class BatchingEngine implements Engine {
transformSet.submitTasks(taskEngine, buffer, startVertex, stack, level); transformSet.submitTasks(taskEngine, buffer, startVertex, stack, level);
startVertex += transformSet.getTotalVertexCount(); startVertex += transformSet.getTotalVertexCount();
} }
}); };
} }
@Override @Override
@ -72,11 +81,7 @@ public class BatchingEngine implements Engine {
return; return;
} }
batchTracker.endBatch(); drawManager.batchTracker.endBatch();
}
@Override
public void delete() {
} }
@Override @Override
@ -86,23 +91,19 @@ public class BatchingEngine implements Engine {
} }
@Override @Override
public void beginFrame(TaskEngine taskEngine, RenderContext context) { public void attachManagers(InstanceManager<?>... listener) {
for (var model : uninitializedModels) { // noop
model.init(batchLists);
}
uninitializedModels.clear();
Vec3 cameraPos = context.camera().getPosition();
var stack = FlwUtil.copyPoseStack(context.stack());
stack.translate(-cameraPos.x, -cameraPos.y, -cameraPos.z);
submitTasks(taskEngine, stack, context.level());
} }
@Override @Override
public void attachManagers(InstanceManager<?>... listener) { public Vec3i getOriginCoordinate() {
// noop return BlockPos.ZERO;
}
@Override
public void delete() {
factories.clear();
drawManager.delete();
} }
@Override @Override

View file

@ -2,7 +2,7 @@ package com.jozufozu.flywheel.backend.instancing.batching;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.function.Consumer; import java.util.function.BiConsumer;
import com.jozufozu.flywheel.api.instancer.InstancedPart; import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.instancer.Instancer; import com.jozufozu.flywheel.api.instancer.Instancer;
@ -12,34 +12,31 @@ import com.jozufozu.flywheel.core.model.Model;
public class CPUInstancerFactory<D extends InstancedPart> implements InstancerFactory<D> { public class CPUInstancerFactory<D extends InstancedPart> implements InstancerFactory<D> {
protected final Map<Model, BatchedModel<D>> models; protected final StructType<D> type;
private final StructType<D> type; private final BiConsumer<CPUInstancer<?>, Model> creationListener;
private final Consumer<BatchedModel<D>> creationListener; protected final Map<Model, CPUInstancer<D>> models = new HashMap<>();
public CPUInstancerFactory(StructType<D> type, Consumer<BatchedModel<D>> creationListener) { public CPUInstancerFactory(StructType<D> type, BiConsumer<CPUInstancer<?>, Model> creationListener) {
this.type = type; this.type = type;
this.creationListener = creationListener; this.creationListener = creationListener;
this.models = new HashMap<>();
} }
@Override @Override
public Instancer<D> model(Model modelKey) { public Instancer<D> model(Model modelKey) {
return models.computeIfAbsent(modelKey, this::createModel).getInstancer(); return models.computeIfAbsent(modelKey, this::createInstancer);
} }
/** // /**
* Clear all instance data without freeing resources. // * Clear all instance data without freeing resources.
*/ // */
public void clear() { // public void clear() {
models.values() // models.values()
.forEach(BatchedModel::clear); // .forEach(BatchedModel::clear);
} // }
private BatchedModel<D> createModel(Model k) { private CPUInstancer<D> createInstancer(Model model) {
var out = new BatchedModel<>(type, k); var instancer = new CPUInstancer<>(type);
creationListener.accept(out); creationListener.accept(instancer, model);
return out; return instancer;
} }
} }

View file

@ -17,13 +17,13 @@ import com.mojang.math.Vector4f;
import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientLevel;
public class TransformSet<D extends InstancedPart> { public class TransformCall<D extends InstancedPart> {
private final CPUInstancer<D> instancer; private final CPUInstancer<D> instancer;
private final Material material; private final Material material;
private final Mesh mesh; private final Mesh mesh;
public TransformSet(CPUInstancer<D> instancer, Material material, Mesh mesh) { public TransformCall(CPUInstancer<D> instancer, Material material, Mesh mesh) {
this.instancer = instancer; this.instancer = instancer;
this.material = material; this.material = material;
this.mesh = mesh; this.mesh = mesh;
@ -51,19 +51,19 @@ public class TransformSet<D extends InstancedPart> {
ReusableVertexList sub = buffer.slice(startVertex, vertexCount); ReusableVertexList sub = buffer.slice(startVertex, vertexCount);
startVertex += vertexCount; startVertex += vertexCount;
pool.submit(() -> drawRange(sub, start, end, stack, level)); pool.submit(() -> transformRange(sub, start, end, stack, level));
} }
} }
private void drawRange(ReusableVertexList vertexList, int from, int to, PoseStack stack, ClientLevel level) { private void transformRange(ReusableVertexList vertexList, int from, int to, PoseStack stack, ClientLevel level) {
drawList(vertexList, instancer.getRange(from, to), stack, level); transformList(vertexList, instancer.getRange(from, to), stack, level);
} }
void drawAll(ReusableVertexList vertexList, PoseStack stack, ClientLevel level) { void transformAll(ReusableVertexList vertexList, PoseStack stack, ClientLevel level) {
drawList(vertexList, instancer.getAll(), stack, level); transformList(vertexList, instancer.getAll(), stack, level);
} }
private void drawList(ReusableVertexList vertexList, List<D> list, PoseStack stack, ClientLevel level) { private void transformList(ReusableVertexList vertexList, List<D> parts, PoseStack stack, ClientLevel level) {
long anchorPtr = vertexList.ptr(); long anchorPtr = vertexList.ptr();
int totalVertexCount = vertexList.getVertexCount(); int totalVertexCount = vertexList.getVertexCount();
@ -72,7 +72,7 @@ public class TransformSet<D extends InstancedPart> {
StructType.VertexTransformer<D> structVertexTransformer = instancer.type.getVertexTransformer(); StructType.VertexTransformer<D> structVertexTransformer = instancer.type.getVertexTransformer();
for (D d : list) { for (D d : parts) {
mesh.write(vertexList); mesh.write(vertexList);
structVertexTransformer.transform(vertexList, d, level); structVertexTransformer.transform(vertexList, d, level);

View file

@ -16,9 +16,9 @@ import com.jozufozu.flywheel.core.model.Model;
*/ */
public class GPUInstancerFactory<D extends InstancedPart> implements InstancerFactory<D> { public class GPUInstancerFactory<D extends InstancedPart> implements InstancerFactory<D> {
protected final Map<Model, GPUInstancer<D>> models = new HashMap<>();
protected final StructType<D> type; protected final StructType<D> type;
private final BiConsumer<GPUInstancer<?>, Model> creationListener; private final BiConsumer<GPUInstancer<?>, Model> creationListener;
protected final Map<Model, GPUInstancer<D>> models = new HashMap<>();
public GPUInstancerFactory(StructType<D> type, BiConsumer<GPUInstancer<?>, Model> creationListener) { public GPUInstancerFactory(StructType<D> type, BiConsumer<GPUInstancer<?>, Model> creationListener) {
this.type = type; this.type = type;
@ -32,7 +32,7 @@ public class GPUInstancerFactory<D extends InstancedPart> implements InstancerFa
private GPUInstancer<D> createInstancer(Model model) { private GPUInstancer<D> createInstancer(Model model) {
var instancer = new GPUInstancer<>(type); var instancer = new GPUInstancer<>(type);
this.creationListener.accept(instancer, model); creationListener.accept(instancer, model);
return instancer; return instancer;
} }
} }

View file

@ -29,8 +29,8 @@ public class InstancingDrawManager {
return renderLists.getOrDefault(stage, DrawSet.EMPTY); return renderLists.getOrDefault(stage, DrawSet.EMPTY);
} }
public void create(GPUInstancer<?> gpuInstancer, Model model) { public void create(GPUInstancer<?> instancer, Model model) {
uninitializedModels.add(new UninitializedModel(gpuInstancer, model)); uninitializedModels.add(new UninitializedModel(instancer, model));
} }
public void flush() { public void flush() {
@ -67,12 +67,12 @@ public class InstancingDrawManager {
private void add(GPUInstancer<?> instancer, Model model) { private void add(GPUInstancer<?> instancer, Model model) {
var meshes = model.getMeshes(); var meshes = model.getMeshes();
for (var entry : meshes.entrySet()) { for (var entry : meshes.entrySet()) {
DrawCall layer = new DrawCall(instancer, entry.getKey(), alloc(entry.getValue())); DrawCall drawCall = new DrawCall(instancer, entry.getKey(), alloc(entry.getValue()));
var material = layer.getMaterial(); var material = drawCall.getMaterial();
var shaderState = new ShaderState(material, layer.getVertexType(), layer.instancer.type); var shaderState = new ShaderState(material, drawCall.getVertexType(), drawCall.instancer.type);
renderLists.computeIfAbsent(material.getRenderStage(), DrawSet::new) renderLists.computeIfAbsent(material.getRenderStage(), DrawSet::new)
.put(shaderState, layer); .put(shaderState, drawCall);
} }
allInstancers.add(instancer); allInstancers.add(instancer);
} }
@ -102,8 +102,8 @@ public class InstancingDrawManager {
drawCalls.clear(); drawCalls.clear();
} }
public void put(ShaderState shaderState, DrawCall layer) { public void put(ShaderState shaderState, DrawCall drawCall) {
drawCalls.put(shaderState, layer); drawCalls.put(shaderState, drawCall);
} }
public boolean isEmpty() { public boolean isEmpty() {
@ -120,6 +120,5 @@ public class InstancingDrawManager {
} }
private record UninitializedModel(GPUInstancer<?> instancer, Model model) { private record UninitializedModel(GPUInstancer<?> instancer, Model model) {
} }
} }

View file

@ -1,5 +1,6 @@
package com.jozufozu.flywheel.backend.instancing.instancing; package com.jozufozu.flywheel.backend.instancing.instancing;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -33,25 +34,22 @@ import net.minecraft.world.phys.Vec3;
public class InstancingEngine implements Engine { public class InstancingEngine implements Engine {
public static int MAX_ORIGIN_DISTANCE = 100;
protected BlockPos originCoordinate = BlockPos.ZERO;
protected final ContextShader context;
protected final Map<StructType<?>, GPUInstancerFactory<?>> factories = new HashMap<>();
protected final InstancingDrawManager drawManager = new InstancingDrawManager(); protected final InstancingDrawManager drawManager = new InstancingDrawManager();
protected final Map<StructType<?>, GPUInstancerFactory<?>> factories = new HashMap<>();
/** /**
* The set of instance managers that are attached to this engine. * The set of instance managers that are attached to this engine.
*/ */
private final WeakHashSet<InstanceManager<?>> instanceManagers; private final WeakHashSet<InstanceManager<?>> instanceManagers = new WeakHashSet<>();
public InstancingEngine(ContextShader context) { protected final ContextShader context;
protected final int sqrMaxOriginDistance;
protected BlockPos originCoordinate = BlockPos.ZERO;
public InstancingEngine(ContextShader context, int sqrMaxOriginDistance) {
this.context = context; this.context = context;
this.sqrMaxOriginDistance = sqrMaxOriginDistance;
this.instanceManagers = new WeakHashSet<>();
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -66,6 +64,11 @@ public class InstancingEngine implements Engine {
return new GPUInstancerFactory<>(type, drawManager::create); return new GPUInstancerFactory<>(type, drawManager::create);
} }
@Override
public void beginFrame(TaskEngine taskEngine, RenderContext context) {
drawManager.flush();
}
@Override @Override
public void renderStage(TaskEngine taskEngine, RenderContext context, RenderStage stage) { public void renderStage(TaskEngine taskEngine, RenderContext context, RenderStage stage) {
var drawSet = drawManager.get(stage); var drawSet = drawManager.get(stage);
@ -79,7 +82,7 @@ public class InstancingEngine implements Engine {
render(drawSet); render(drawSet);
} }
private void setup() { protected void setup() {
GlTextureUnit.T2.makeActive(); GlTextureUnit.T2.makeActive();
Minecraft.getInstance().gameRenderer.lightTexture().turnOnLightLayer(); Minecraft.getInstance().gameRenderer.lightTexture().turnOnLightLayer();
@ -91,10 +94,6 @@ public class InstancingEngine implements Engine {
} }
protected void render(InstancingDrawManager.DrawSet drawSet) { protected void render(InstancingDrawManager.DrawSet drawSet) {
if (drawSet.isEmpty()) {
return;
}
for (var entry : drawSet) { for (var entry : drawSet) {
var shader = entry.getKey(); var shader = entry.getKey();
var drawCalls = entry.getValue(); var drawCalls = entry.getValue();
@ -118,7 +117,6 @@ public class InstancingEngine implements Engine {
} }
protected void setup(ShaderState desc) { protected void setup(ShaderState desc) {
VertexType vertexType = desc.vertex(); VertexType vertexType = desc.vertex();
FileResolution instanceShader = desc.instance() FileResolution instanceShader = desc.instance()
.getInstanceShader(); .getInstanceShader();
@ -131,22 +129,6 @@ public class InstancingEngine implements Engine {
UniformBuffer.getInstance().sync(); UniformBuffer.getInstance().sync();
} }
@Override
public void delete() {
factories.clear();
drawManager.delete();
}
@Override
public Vec3i getOriginCoordinate() {
return originCoordinate;
}
@Override
public void attachManagers(InstanceManager<?>... listener) {
instanceManagers.addAll(List.of(listener));
}
@Override @Override
public boolean maintainOriginCoordinate(Camera camera) { public boolean maintainOriginCoordinate(Camera camera) {
Vec3 cameraPos = camera.getPosition(); Vec3 cameraPos = camera.getPosition();
@ -155,18 +137,13 @@ public class InstancingEngine implements Engine {
.subtract(cameraPos) .subtract(cameraPos)
.lengthSqr(); .lengthSqr();
if (distanceSqr > MAX_ORIGIN_DISTANCE * MAX_ORIGIN_DISTANCE) { if (distanceSqr > sqrMaxOriginDistance) {
shiftListeners(Mth.floor(cameraPos.x), Mth.floor(cameraPos.y), Mth.floor(cameraPos.z)); shiftListeners(Mth.floor(cameraPos.x), Mth.floor(cameraPos.y), Mth.floor(cameraPos.z));
return true; return true;
} }
return false; return false;
} }
@Override
public void beginFrame(TaskEngine taskEngine, RenderContext context) {
drawManager.flush();
}
private void shiftListeners(int cX, int cY, int cZ) { private void shiftListeners(int cX, int cY, int cZ) {
originCoordinate = new BlockPos(cX, cY, cZ); originCoordinate = new BlockPos(cX, cY, cZ);
@ -175,6 +152,22 @@ public class InstancingEngine implements Engine {
instanceManagers.forEach(InstanceManager::onOriginShift); instanceManagers.forEach(InstanceManager::onOriginShift);
} }
@Override
public void attachManagers(InstanceManager<?>... listener) {
Collections.addAll(instanceManagers, listener);
}
@Override
public Vec3i getOriginCoordinate() {
return originCoordinate;
}
@Override
public void delete() {
factories.clear();
drawManager.delete();
}
@Override @Override
public void addDebugInfo(List<String> info) { public void addDebugInfo(List<String> info) {
info.add("GL33 Instanced Arrays"); info.add("GL33 Instanced Arrays");

View file

@ -21,7 +21,6 @@ import com.jozufozu.flywheel.core.model.Mesh;
public class MeshPool { public class MeshPool {
private final VertexType vertexType; private final VertexType vertexType;
private final Map<Mesh, BufferedMesh> meshes = new HashMap<>(); private final Map<Mesh, BufferedMesh> meshes = new HashMap<>();
private final List<BufferedMesh> allBuffered = new ArrayList<>(); private final List<BufferedMesh> allBuffered = new ArrayList<>();