StructType doesn't need #asBatched and #asInstanced

- More organized this way
 - BatchingTransformer function moved into Batched
This commit is contained in:
Jozufozu 2021-12-20 22:38:33 -08:00
parent a43fe2bc9a
commit 4908abc9e0
17 changed files with 70 additions and 79 deletions

View file

@ -1,11 +1,8 @@
package com.jozufozu.flywheel.api.struct;
import com.jozufozu.flywheel.core.model.ModelTransformer;
public interface Batched<S> extends StructType<S> {
BatchingTransformer<S> getTransformer();
@Override
default Batched<S> asBatched() {
return this;
}
void transform(S d, ModelTransformer.Params b);
}

View file

@ -1,9 +0,0 @@
package com.jozufozu.flywheel.api.struct;
import com.jozufozu.flywheel.core.model.ModelTransformer;
@FunctionalInterface
public interface BatchingTransformer<S> {
void transform(S s, ModelTransformer.Params b);
}

View file

@ -14,8 +14,4 @@ public interface Instanced<S> extends StructType<S> {
ResourceLocation getProgramSpec();
@Override
default Instanced<S> asInstanced() {
return this;
}
}

View file

@ -18,7 +18,4 @@ public interface StructType<S> {
*/
VertexFormat format();
Instanced<S> asInstanced();
Batched<S> asBatched();
}

View file

@ -2,6 +2,7 @@ package com.jozufozu.flywheel.backend.instancing;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.function.Supplier;
import com.jozufozu.flywheel.api.InstanceData;
import com.jozufozu.flywheel.api.Instancer;
@ -10,13 +11,13 @@ import com.jozufozu.flywheel.core.model.Model;
public abstract class AbstractInstancer<D extends InstanceData> implements Instancer<D> {
protected final StructType<D> type;
protected final Supplier<D> type;
protected final Model modelData;
protected final ArrayList<D> data = new ArrayList<>();
protected boolean anyToRemove;
protected AbstractInstancer(StructType<D> type, Model modelData) {
protected AbstractInstancer(Supplier<D> type, Model modelData) {
this.type = type;
this.modelData = modelData;
}
@ -26,7 +27,7 @@ public abstract class AbstractInstancer<D extends InstanceData> implements Insta
*/
@Override
public D createInstance() {
return _add(type.create());
return _add(type.get());
}
/**

View file

@ -7,7 +7,7 @@ import java.util.function.Supplier;
import com.jozufozu.flywheel.api.InstanceData;
import com.jozufozu.flywheel.api.Instancer;
import com.jozufozu.flywheel.api.Material;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.struct.Batched;
import com.jozufozu.flywheel.core.model.Model;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
@ -15,9 +15,9 @@ import com.mojang.blaze3d.vertex.VertexConsumer;
public class BatchedMaterial<D extends InstanceData> implements Material<D> {
protected final Map<Object, CPUInstancer<D>> models;
private final StructType<D> type;
private final Batched<D> type;
public BatchedMaterial(StructType<D> type) {
public BatchedMaterial(Batched<D> type) {
this.type = type;
this.models = new HashMap<>();

View file

@ -5,6 +5,7 @@ import java.util.Map;
import com.jozufozu.flywheel.api.InstanceData;
import com.jozufozu.flywheel.api.MaterialGroup;
import com.jozufozu.flywheel.api.struct.Batched;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.backend.instancing.TaskEngine;
import com.jozufozu.flywheel.backend.model.DirectBufferBuilder;
@ -19,7 +20,7 @@ public class BatchedMaterialGroup implements MaterialGroup {
protected final RenderType state;
private final Map<StructType<? extends InstanceData>, BatchedMaterial<?>> materials = new HashMap<>();
private final Map<Batched<? extends InstanceData>, BatchedMaterial<?>> materials = new HashMap<>();
public BatchedMaterialGroup(RenderType state) {
this.state = state;
@ -27,8 +28,12 @@ public class BatchedMaterialGroup implements MaterialGroup {
@SuppressWarnings("unchecked")
@Override
public <D extends InstanceData> BatchedMaterial<D> material(StructType<D> spec) {
return (BatchedMaterial<D>) materials.computeIfAbsent(spec, BatchedMaterial::new);
public <D extends InstanceData> BatchedMaterial<D> material(StructType<D> type) {
if (type instanceof Batched<D> batched) {
return (BatchedMaterial<D>) materials.computeIfAbsent(batched, BatchedMaterial::new);
} else {
throw new ClassCastException("Cannot use type '" + type + "' with CPU instancing.");
}
}
public void render(PoseStack stack, MultiBufferSource source, TaskEngine pool) {

View file

@ -49,9 +49,7 @@ public class BatchingEngine implements Engine {
stack.translate(-event.camX, -event.camY, -event.camZ);
for (Map.Entry<RenderType, BatchedMaterialGroup> entry : layers.get(event.getLayer()).entrySet()) {
BatchedMaterialGroup group = entry.getValue();
for (BatchedMaterialGroup group : layers.get(event.getLayer()).values()) {
group.render(stack, buffers, taskEngine);
}

View file

@ -1,7 +1,7 @@
package com.jozufozu.flywheel.backend.instancing.batching;
import com.jozufozu.flywheel.api.InstanceData;
import com.jozufozu.flywheel.api.struct.BatchingTransformer;
import com.jozufozu.flywheel.api.struct.Batched;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.backend.instancing.AbstractInstancer;
import com.jozufozu.flywheel.backend.instancing.TaskEngine;
@ -13,22 +13,17 @@ import com.mojang.blaze3d.vertex.VertexConsumer;
public class CPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
private final BatchingTransformer<D> transform;
private final Batched<D> batchingType;
private final ModelTransformer sbb;
private final ModelTransformer.Params defaultParams;
public CPUInstancer(StructType<D> type, Model modelData) {
super(type, modelData);
public CPUInstancer(Batched<D> type, Model modelData) {
super(type::create, modelData);
batchingType = type;
sbb = new ModelTransformer(modelData);
defaultParams = ModelTransformer.Params.defaultParams();
transform = type.asBatched()
.getTransformer();
if (transform == null) {
throw new NullPointerException("Cannot batch " + type.toString());
}
}
void submitTasks(PoseStack stack, TaskEngine pool, DirectVertexConsumer consumer) {
@ -56,7 +51,7 @@ public class CPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
ModelTransformer.Params params = defaultParams.copy();
for (D d : data.subList(from, to)) {
transform.transform(d, params);
batchingType.transform(d, params);
sbb.renderInto(params, stack, buffer);
@ -67,7 +62,7 @@ public class CPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
void drawAll(PoseStack stack, VertexConsumer buffer) {
ModelTransformer.Params params = defaultParams.copy();
for (D d : data) {
transform.transform(d, params);
batchingType.transform(d, params);
sbb.renderInto(params, stack, buffer);

View file

@ -4,6 +4,7 @@ import java.util.BitSet;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.InstanceData;
import com.jozufozu.flywheel.api.struct.Instanced;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.struct.StructWriter;
import com.jozufozu.flywheel.backend.Backend;
@ -23,6 +24,7 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
private final ModelAllocator modelAllocator;
private final VertexFormat instanceFormat;
private final Instanced<D> instancedType;
private IBufferedModel model;
private GlVertexArray vao;
@ -34,10 +36,11 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
protected boolean anyToUpdate;
public GPUInstancer(StructType<D> type, Model model, ModelAllocator modelAllocator) {
super(type, model);
public GPUInstancer(Instanced<D> type, Model model, ModelAllocator modelAllocator) {
super(type::create, model);
this.modelAllocator = modelAllocator;
this.instanceFormat = type.format();
instancedType = type;
}
@Override
@ -152,8 +155,7 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
try (MappedBuffer mapped = instanceVBO.getBuffer(0, glBufferSize)) {
final StructWriter<D> writer = type.asInstanced()
.getWriter(mapped);
final StructWriter<D> writer = instancedType.getWriter(mapped);
for (int i = 0; i < size; i++) {
final D element = data.get(i);
@ -176,8 +178,7 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
instanceVBO.alloc(glBufferSize);
try (MappedBuffer buffer = instanceVBO.getBuffer(0, glBufferSize)) {
StructWriter<D> writer = type.asInstanced()
.getWriter(buffer);
StructWriter<D> writer = instancedType.getWriter(buffer);
for (D datum : data) {
writer.write(datum);
}

View file

@ -8,7 +8,7 @@ import com.google.common.cache.CacheBuilder;
import com.jozufozu.flywheel.api.InstanceData;
import com.jozufozu.flywheel.api.Instancer;
import com.jozufozu.flywheel.api.Material;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.struct.Instanced;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.RenderWork;
import com.jozufozu.flywheel.backend.model.ImmediateAllocator;
@ -25,10 +25,10 @@ public class InstancedMaterial<D extends InstanceData> implements Material<D> {
final ModelAllocator allocator;
protected final Cache<Object, GPUInstancer<D>> models;
protected final StructType<D> type;
protected final Instanced<D> type;
public InstancedMaterial(StructType<D> spec) {
this.type = spec;
public InstancedMaterial(Instanced<D> type) {
this.type = type;
if (Backend.getInstance().compat.onAMDWindows()) {
allocator = ImmediateAllocator.INSTANCE;

View file

@ -6,6 +6,7 @@ import java.util.Map;
import com.jozufozu.flywheel.api.InstanceData;
import com.jozufozu.flywheel.api.MaterialGroup;
import com.jozufozu.flywheel.api.struct.Instanced;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.backend.model.ModelPool;
import com.jozufozu.flywheel.core.shader.WorldProgram;
@ -25,7 +26,7 @@ public class InstancedMaterialGroup<P extends WorldProgram> implements MaterialG
protected final InstancingEngine<P> owner;
protected final RenderType type;
private final Map<StructType<? extends InstanceData>, InstancedMaterial<?>> materials = new HashMap<>();
private final Map<Instanced<? extends InstanceData>, InstancedMaterial<?>> materials = new HashMap<>();
public InstancedMaterialGroup(InstancingEngine<P> owner, RenderType type) {
this.owner = owner;
@ -34,8 +35,12 @@ public class InstancedMaterialGroup<P extends WorldProgram> implements MaterialG
@SuppressWarnings("unchecked")
@Override
public <D extends InstanceData> InstancedMaterial<D> material(StructType<D> spec) {
return (InstancedMaterial<D>) materials.computeIfAbsent(spec, InstancedMaterial::new);
public <D extends InstanceData> InstancedMaterial<D> material(StructType<D> type) {
if (type instanceof Instanced<D> instanced) {
return (InstancedMaterial<D>) materials.computeIfAbsent(instanced, InstancedMaterial::new);
} else {
throw new ClassCastException("Cannot use type '" + type + "' with GPU instancing.");
}
}
public void render(Matrix4f viewProjection, double camX, double camY, double camZ) {
@ -46,7 +51,7 @@ public class InstancedMaterialGroup<P extends WorldProgram> implements MaterialG
}
protected void renderAll(Matrix4f viewProjection, double camX, double camY, double camZ) {
for (Map.Entry<StructType<? extends InstanceData>, InstancedMaterial<?>> entry : materials.entrySet()) {
for (Map.Entry<Instanced<? extends InstanceData>, InstancedMaterial<?>> entry : materials.entrySet()) {
InstancedMaterial<?> material = entry.getValue();
if (material.nothingToRender()) continue;
@ -61,7 +66,6 @@ public class InstancedMaterialGroup<P extends WorldProgram> implements MaterialG
}
P program = owner.getProgram(entry.getKey()
.asInstanced()
.getProgramSpec()).get();
program.bind();

View file

@ -109,6 +109,7 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
}
private Stream<InstancedMaterialGroup<P>> getGroupsToRender(@Nullable RenderLayer layer) {
// layer is null when this is called from CrumblingRenderer
if (layer != null) {
return layers.get(layer)
.values()

View file

@ -0,0 +1,6 @@
@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
package com.jozufozu.flywheel.backend.struct;
import javax.annotation.ParametersAreNonnullByDefault;
import net.minecraft.MethodsReturnNonnullByDefault;

View file

@ -2,9 +2,11 @@ package com.jozufozu.flywheel.core;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.function.Supplier;
import java.util.stream.Stream;
import com.jozufozu.flywheel.api.struct.Instanced;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.ShaderContext;
import com.jozufozu.flywheel.backend.pipeline.ShaderPipeline;
@ -87,8 +89,9 @@ public class WorldContext<P extends WorldProgram> implements ShaderContext<P> {
if (specStream == null) {
specStream = () -> backend.allMaterials()
.stream()
.map(type -> type.asInstanced()
.getProgramSpec());
.map(t -> t instanceof Instanced<?> i ? i : null)
.filter(Objects::nonNull)
.map(Instanced::getProgramSpec);
}
return new WorldContext<>(backend, name, specStream, pipeline);
}

View file

@ -1,13 +1,13 @@
package com.jozufozu.flywheel.core.materials.model;
import com.jozufozu.flywheel.api.struct.Batched;
import com.jozufozu.flywheel.api.struct.BatchingTransformer;
import com.jozufozu.flywheel.api.struct.Instanced;
import com.jozufozu.flywheel.api.struct.StructWriter;
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.core.Formats;
import com.jozufozu.flywheel.core.Programs;
import com.jozufozu.flywheel.core.model.ModelTransformer;
import net.minecraft.resources.ResourceLocation;
@ -34,11 +34,9 @@ public class ModelType implements Instanced<ModelData>, Batched<ModelData> {
}
@Override
public BatchingTransformer<ModelData> getTransformer() {
return (d, b) -> {
b.transform(d.model, d.normal)
.color(d.r, d.g, d.b, d.a)
.light(d.getPackedLight());
};
public void transform(ModelData d, ModelTransformer.Params b) {
b.transform(d.model, d.normal)
.color(d.r, d.g, d.b, d.a)
.light(d.getPackedLight());
}
}

View file

@ -1,13 +1,13 @@
package com.jozufozu.flywheel.core.materials.oriented;
import com.jozufozu.flywheel.api.struct.Batched;
import com.jozufozu.flywheel.api.struct.BatchingTransformer;
import com.jozufozu.flywheel.api.struct.Instanced;
import com.jozufozu.flywheel.api.struct.StructWriter;
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.core.Formats;
import com.jozufozu.flywheel.core.Programs;
import com.jozufozu.flywheel.core.model.ModelTransformer;
import com.mojang.math.Quaternion;
import net.minecraft.resources.ResourceLocation;
@ -35,13 +35,11 @@ public class OrientedType implements Instanced<OrientedData>, Batched<OrientedDa
}
@Override
public BatchingTransformer<OrientedData> getTransformer() {
return (d, sbb) -> {
sbb.light(d.getPackedLight())
.color(d.r, d.g, d.b, d.a)
.translate(d.posX + d.pivotX, d.posY + d.pivotY, d.posZ + d.pivotZ)
.multiply(new Quaternion(d.qX, d.qY, d.qZ, d.qW))
.translate(-d.pivotX, -d.pivotY, -d.pivotZ);
};
public void transform(OrientedData d, ModelTransformer.Params b) {
b.light(d.getPackedLight())
.color(d.r, d.g, d.b, d.a)
.translate(d.posX + d.pivotX, d.posY + d.pivotY, d.posZ + d.pivotZ)
.multiply(new Quaternion(d.qX, d.qY, d.qZ, d.qW))
.translate(-d.pivotX, -d.pivotY, -d.pivotZ);
}
}