Remove InstancerFactory

This commit is contained in:
PepperCode1 2023-03-24 16:15:29 -07:00
parent 79464361d2
commit bbcf019bc2
18 changed files with 84 additions and 191 deletions

View file

@ -1,15 +0,0 @@
package com.jozufozu.flywheel.api.instancer;
import com.jozufozu.flywheel.core.model.Model;
public interface InstancerFactory<D extends InstancedPart> {
/**
* Get an instancer for the given model. Calling this method twice with the same key will return the same instancer.
*
* @param modelKey An object that uniquely identifies and provides the model.
* @return An instancer for the given model, capable of rendering many copies for little cost.
*/
Instancer<D> model(Model modelKey);
}

View file

@ -1,12 +1,18 @@
package com.jozufozu.flywheel.api.instancer;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.core.model.Model;
import net.minecraft.core.Vec3i;
public interface InstancerManager {
<D extends InstancedPart> InstancerFactory<D> factory(StructType<D> type);
/**
* Get an instancer for the given struct type and model. Calling this method twice with the same arguments will return the same instancer.
*
* @return An instancer for the given struct type and model.
*/
<D extends InstancedPart> Instancer<D> instancer(StructType<D> type, Model model);
Vec3i getOriginCoordinate();

View file

@ -0,0 +1,8 @@
package com.jozufozu.flywheel.backend.instancing;
import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.core.model.Model;
public record InstancerKey<D extends InstancedPart>(StructType<D> type, Model model) {
}

View file

@ -1,18 +1,16 @@
package com.jozufozu.flywheel.backend.instancing.batching;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jetbrains.annotations.NotNull;
import com.jozufozu.flywheel.api.RenderStage;
import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.instancer.Instancer;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.backend.instancing.Engine;
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
import com.jozufozu.flywheel.backend.instancing.TaskEngine;
import com.jozufozu.flywheel.core.RenderContext;
import com.jozufozu.flywheel.core.model.Model;
import com.jozufozu.flywheel.util.FlwUtil;
import com.mojang.blaze3d.vertex.PoseStack;
@ -25,18 +23,10 @@ import net.minecraft.world.phys.Vec3;
public class BatchingEngine implements Engine {
protected final BatchingTransformManager transformManager = new BatchingTransformManager();
protected final BatchingDrawTracker drawTracker = new BatchingDrawTracker();
protected final Map<StructType<?>, CPUInstancerFactory<?>> factories = new HashMap<>();
@SuppressWarnings("unchecked")
@NotNull
@Override
public <D extends InstancedPart> CPUInstancerFactory<D> factory(StructType<D> type) {
return (CPUInstancerFactory<D>) factories.computeIfAbsent(type, this::createFactory);
}
@NotNull
private <D extends InstancedPart> CPUInstancerFactory<D> createFactory(StructType<D> type) {
return new CPUInstancerFactory<>(type, transformManager::create);
public <D extends InstancedPart> Instancer<D> instancer(StructType<D> type, Model model) {
return transformManager.getInstancer(type, model);
}
@Override
@ -105,7 +95,6 @@ public class BatchingEngine implements Engine {
@Override
public void delete() {
factories.clear();
transformManager.delete();
}

View file

@ -15,6 +15,10 @@ 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.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.instancer.Instancer;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.backend.instancing.InstancerKey;
import com.jozufozu.flywheel.core.model.Mesh;
import com.jozufozu.flywheel.core.model.Model;
import com.mojang.blaze3d.vertex.VertexFormat;
@ -22,6 +26,7 @@ import com.mojang.blaze3d.vertex.VertexFormat;
import net.minecraft.client.renderer.RenderType;
public class BatchingTransformManager {
private final Map<InstancerKey<?>, CPUInstancer<?>> instancers = new HashMap<>();
private final List<UninitializedModel> uninitializedModels = new ArrayList<>();
private final List<CPUInstancer<?>> allInstancers = new ArrayList<>();
private final Map<RenderStage, TransformSet> transformSets = new EnumMap<>(RenderStage.class);
@ -36,8 +41,16 @@ public class BatchingTransformManager {
return transformSetsView;
}
public void create(CPUInstancer<?> instancer, Model model) {
uninitializedModels.add(new UninitializedModel(instancer, model));
@SuppressWarnings("unchecked")
public <D extends InstancedPart> Instancer<D> getInstancer(StructType<D> type, Model model) {
InstancerKey<D> key = new InstancerKey<>(type, model);
CPUInstancer<D> instancer = (CPUInstancer<D>) instancers.get(key);
if (instancer == null) {
instancer = new CPUInstancer<>(type);
instancers.put(key, instancer);
uninitializedModels.add(new UninitializedModel(instancer, model));
}
return instancer;
}
public void flush() {
@ -52,6 +65,8 @@ public class BatchingTransformManager {
}
public void delete() {
instancers.clear();
meshPools.values()
.forEach(BatchedMeshPool::delete);
meshPools.clear();

View file

@ -1,34 +0,0 @@
package com.jozufozu.flywheel.backend.instancing.batching;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.instancer.Instancer;
import com.jozufozu.flywheel.api.instancer.InstancerFactory;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.core.model.Model;
public class CPUInstancerFactory<D extends InstancedPart> implements InstancerFactory<D> {
protected final StructType<D> type;
private final BiConsumer<CPUInstancer<?>, Model> creationListener;
protected final Map<Model, CPUInstancer<D>> models = new HashMap<>();
public CPUInstancerFactory(StructType<D> type, BiConsumer<CPUInstancer<?>, Model> creationListener) {
this.type = type;
this.creationListener = creationListener;
}
@Override
public Instancer<D> model(Model modelKey) {
return models.computeIfAbsent(modelKey, this::createInstancer);
}
private CPUInstancer<D> createInstancer(Model model) {
var instancer = new CPUInstancer<>(type);
creationListener.accept(instancer, model);
return instancer;
}
}

View file

@ -6,12 +6,8 @@ import java.util.List;
import com.jozufozu.flywheel.api.instance.DynamicInstance;
import com.jozufozu.flywheel.api.instance.TickableInstance;
import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.instancer.InstancerFactory;
import com.jozufozu.flywheel.api.instancer.InstancerManager;
import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
import com.jozufozu.flywheel.core.structs.StructTypes;
import com.jozufozu.flywheel.core.structs.oriented.OrientedPart;
import com.jozufozu.flywheel.core.structs.transformed.TransformedPart;
import com.jozufozu.flywheel.util.box.GridAlignedBB;
import com.jozufozu.flywheel.util.box.ImmutableBox;
import com.jozufozu.flywheel.util.joml.FrustumIntersection;

View file

@ -6,19 +6,30 @@ import java.util.List;
import java.util.Map;
import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.instancer.Instancer;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.backend.instancing.InstancerKey;
import com.jozufozu.flywheel.core.model.Model;
import com.jozufozu.flywheel.util.Pair;
public class IndirectDrawManager {
private final Map<InstancerKey<?>, IndirectInstancer<?>> instancers = new HashMap<>();
private final List<UninitializedModel> uninitializedModels = new ArrayList<>();
private final List<IndirectInstancer<?>> allInstancers = new ArrayList<>();
public final Map<Pair<StructType<?>, VertexType>, IndirectCullingGroup<?>> renderLists = new HashMap<>();
public void create(IndirectInstancer<?> instancer, Model model) {
uninitializedModels.add(new UninitializedModel(instancer, model));
@SuppressWarnings("unchecked")
public <D extends InstancedPart> Instancer<D> getInstancer(StructType<D> type, Model model) {
InstancerKey<D> key = new InstancerKey<>(type, model);
IndirectInstancer<D> instancer = (IndirectInstancer<D>) instancers.get(key);
if (instancer == null) {
instancer = new IndirectInstancer<>(type);
instancers.put(key, instancer);
uninitializedModels.add(new UninitializedModel(instancer, model));
}
return instancer;
}
public void flush() {
@ -33,6 +44,8 @@ public class IndirectDrawManager {
}
public void delete() {
instancers.clear();
renderLists.values()
.forEach(IndirectCullingGroup::delete);
renderLists.clear();

View file

@ -1,16 +1,14 @@
package com.jozufozu.flywheel.backend.instancing.indirect;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jetbrains.annotations.NotNull;
import org.lwjgl.opengl.GL32;
import com.jozufozu.flywheel.api.RenderStage;
import com.jozufozu.flywheel.api.context.ContextShader;
import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.instancer.Instancer;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.backend.gl.GlStateTracker;
import com.jozufozu.flywheel.backend.gl.GlTextureUnit;
@ -18,6 +16,7 @@ import com.jozufozu.flywheel.backend.instancing.Engine;
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
import com.jozufozu.flywheel.backend.instancing.TaskEngine;
import com.jozufozu.flywheel.core.RenderContext;
import com.jozufozu.flywheel.core.model.Model;
import com.jozufozu.flywheel.util.WeakHashSet;
import com.mojang.blaze3d.systems.RenderSystem;
@ -31,7 +30,6 @@ import net.minecraft.world.phys.Vec3;
public class IndirectEngine implements Engine {
protected final IndirectDrawManager drawManager = new IndirectDrawManager();
protected final Map<StructType<?>, IndirectInstancerFactory<?>> factories = new HashMap<>();
/**
* The set of instance managers that are attached to this engine.
@ -48,16 +46,9 @@ public class IndirectEngine implements Engine {
this.sqrMaxOriginDistance = sqrMaxOriginDistance;
}
@SuppressWarnings("unchecked")
@NotNull
@Override
public <D extends InstancedPart> IndirectInstancerFactory<D> factory(StructType<D> type) {
return (IndirectInstancerFactory<D>) factories.computeIfAbsent(type, this::createFactory);
}
@NotNull
private <D extends InstancedPart> IndirectInstancerFactory<D> createFactory(StructType<D> type) {
return new IndirectInstancerFactory<>(type, drawManager::create);
public <D extends InstancedPart> Instancer<D> instancer(StructType<D> type, Model model) {
return drawManager.getInstancer(type, model);
}
@Override
@ -124,7 +115,6 @@ public class IndirectEngine implements Engine {
@Override
public void delete() {
factories.clear();
drawManager.delete();
}

View file

@ -1,34 +0,0 @@
package com.jozufozu.flywheel.backend.instancing.indirect;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.instancer.Instancer;
import com.jozufozu.flywheel.api.instancer.InstancerFactory;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.core.model.Model;
public class IndirectInstancerFactory<D extends InstancedPart> implements InstancerFactory<D> {
protected final StructType<D> type;
private final BiConsumer<IndirectInstancer<?>, Model> creationListener;
protected final Map<Model, IndirectInstancer<D>> models = new HashMap<>();
public IndirectInstancerFactory(StructType<D> type, BiConsumer<IndirectInstancer<?>, Model> creationListener) {
this.type = type;
this.creationListener = creationListener;
}
@Override
public Instancer<D> model(Model modelKey) {
return models.computeIfAbsent(modelKey, this::createInstancer);
}
private IndirectInstancer<D> createInstancer(Model model) {
var instancer = new IndirectInstancer<>(type);
creationListener.accept(instancer, model);
return instancer;
}
}

View file

@ -1,38 +0,0 @@
package com.jozufozu.flywheel.backend.instancing.instancing;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.instancer.Instancer;
import com.jozufozu.flywheel.api.instancer.InstancerFactory;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.core.model.Model;
/**
* A collection of Instancers that all have the same format.
* @param <D>
*/
public class GPUInstancerFactory<D extends InstancedPart> implements InstancerFactory<D> {
protected final StructType<D> type;
private final BiConsumer<GPUInstancer<?>, Model> creationListener;
protected final Map<Model, GPUInstancer<D>> models = new HashMap<>();
public GPUInstancerFactory(StructType<D> type, BiConsumer<GPUInstancer<?>, Model> creationListener) {
this.type = type;
this.creationListener = creationListener;
}
@Override
public Instancer<D> model(Model modelKey) {
return models.computeIfAbsent(modelKey, this::createInstancer);
}
private GPUInstancer<D> createInstancer(Model model) {
var instancer = new GPUInstancer<>(type);
creationListener.accept(instancer, model);
return instancer;
}
}

View file

@ -14,12 +14,17 @@ 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.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.instancer.Instancer;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.backend.instancing.InstancerKey;
import com.jozufozu.flywheel.core.model.Mesh;
import com.jozufozu.flywheel.core.model.Model;
public class InstancingDrawManager {
private final Map<InstancerKey<?>, GPUInstancer<?>> instancers = new HashMap<>();
private final List<UninitializedModel> uninitializedModels = new ArrayList<>();
private final List<GPUInstancer<?>> allInstancers = new ArrayList<>();
private final Map<RenderStage, DrawSet> renderLists = new EnumMap<>(RenderStage.class);
@ -29,8 +34,16 @@ public class InstancingDrawManager {
return renderLists.getOrDefault(stage, DrawSet.EMPTY);
}
public void create(GPUInstancer<?> instancer, Model model) {
uninitializedModels.add(new UninitializedModel(instancer, model));
@SuppressWarnings("unchecked")
public <D extends InstancedPart> Instancer<D> getInstancer(StructType<D> type, Model model) {
InstancerKey<D> key = new InstancerKey<>(type, model);
GPUInstancer<D> instancer = (GPUInstancer<D>) instancers.get(key);
if (instancer == null) {
instancer = new GPUInstancer<>(type);
instancers.put(key, instancer);
uninitializedModels.add(new UninitializedModel(instancer, model));
}
return instancer;
}
public void flush() {
@ -48,6 +61,8 @@ public class InstancingDrawManager {
}
public void delete() {
instancers.clear();
meshPools.values()
.forEach(InstancedMeshPool::delete);
meshPools.clear();

View file

@ -1,16 +1,14 @@
package com.jozufozu.flywheel.backend.instancing.instancing;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jetbrains.annotations.NotNull;
import org.lwjgl.opengl.GL32;
import com.jozufozu.flywheel.api.RenderStage;
import com.jozufozu.flywheel.api.context.ContextShader;
import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.instancer.Instancer;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.backend.gl.GlStateTracker;
import com.jozufozu.flywheel.backend.gl.GlTextureUnit;
@ -20,6 +18,7 @@ import com.jozufozu.flywheel.backend.instancing.PipelineCompiler;
import com.jozufozu.flywheel.backend.instancing.TaskEngine;
import com.jozufozu.flywheel.core.Components;
import com.jozufozu.flywheel.core.RenderContext;
import com.jozufozu.flywheel.core.model.Model;
import com.jozufozu.flywheel.core.uniform.UniformBuffer;
import com.jozufozu.flywheel.util.WeakHashSet;
import com.mojang.blaze3d.systems.RenderSystem;
@ -34,7 +33,6 @@ import net.minecraft.world.phys.Vec3;
public class InstancingEngine implements Engine {
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.
@ -51,16 +49,9 @@ public class InstancingEngine implements Engine {
this.sqrMaxOriginDistance = sqrMaxOriginDistance;
}
@SuppressWarnings("unchecked")
@NotNull
@Override
public <D extends InstancedPart> GPUInstancerFactory<D> factory(StructType<D> type) {
return (GPUInstancerFactory<D>) factories.computeIfAbsent(type, this::createFactory);
}
@NotNull
private <D extends InstancedPart> GPUInstancerFactory<D> createFactory(StructType<D> type) {
return new GPUInstancerFactory<>(type, drawManager::create);
public <D extends InstancedPart> Instancer<D> instancer(StructType<D> type, Model model) {
return drawManager.getInstancer(type, model);
}
@Override
@ -167,7 +158,6 @@ public class InstancingEngine implements Engine {
@Override
public void delete() {
factories.clear();
drawManager.delete();
}

View file

@ -72,8 +72,7 @@ public class BellInstance extends BlockEntityInstance<BellBlockEntity> implement
}
private OrientedPart createBellInstance() {
return instancerManager.factory(StructTypes.ORIENTED)
.model(MODEL)
return instancerManager.instancer(StructTypes.ORIENTED, MODEL)
.createInstance();
}

View file

@ -123,15 +123,13 @@ public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends Block
private OrientedPart baseInstance() {
return instancerManager.factory(StructTypes.ORIENTED)
.model(BASE.apply(chestType, sprite))
return instancerManager.instancer(StructTypes.ORIENTED, BASE.apply(chestType, sprite))
.createInstance();
}
private TransformedPart lidInstance() {
return instancerManager.factory(StructTypes.TRANSFORMED)
.model(LID.apply(chestType, sprite))
return instancerManager.instancer(StructTypes.TRANSFORMED, LID.apply(chestType, sprite))
.createInstance();
}

View file

@ -167,14 +167,12 @@ public class MinecartInstance<T extends AbstractMinecart> extends EntityInstance
if (shape == RenderShape.INVISIBLE)
return null;
return instancerManager.factory(StructTypes.TRANSFORMED)
.model(Models.block(blockState))
return instancerManager.instancer(StructTypes.TRANSFORMED, Models.block(blockState))
.createInstance();
}
private TransformedPart getBody() {
return instancerManager.factory(StructTypes.TRANSFORMED)
.model(MODEL)
return instancerManager.instancer(StructTypes.TRANSFORMED, MODEL)
.createInstance();
}

View file

@ -105,14 +105,12 @@ public class ShulkerBoxInstance extends BlockEntityInstance<ShulkerBoxBlockEntit
}
private TransformedPart makeBaseInstance() {
return instancerManager.factory(StructTypes.TRANSFORMED)
.model(BASE.apply(texture))
return instancerManager.instancer(StructTypes.TRANSFORMED, BASE.apply(texture))
.createInstance();
}
private TransformedPart makeLidInstance() {
return instancerManager.factory(StructTypes.TRANSFORMED)
.model(LID.apply(texture))
return instancerManager.instancer(StructTypes.TRANSFORMED, LID.apply(texture))
.createInstance();
}

View file

@ -247,8 +247,7 @@ public class ExampleEffect implements Effect {
@Override
public void init() {
instance = instancerManager.factory(StructTypes.TRANSFORMED)
.model(Models.block(Blocks.SHROOMLIGHT.defaultBlockState()))
instance = instancerManager.instancer(StructTypes.TRANSFORMED, Models.block(Blocks.SHROOMLIGHT.defaultBlockState()))
.createInstance();
instance.setBlockLight(15)