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

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(); ResourceLocation getProgramSpec();
@Override
default Instanced<S> asInstanced() {
return this;
}
} }

View file

@ -18,7 +18,4 @@ public interface StructType<S> {
*/ */
VertexFormat format(); 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.ArrayList;
import java.util.BitSet; import java.util.BitSet;
import java.util.function.Supplier;
import com.jozufozu.flywheel.api.InstanceData; import com.jozufozu.flywheel.api.InstanceData;
import com.jozufozu.flywheel.api.Instancer; 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> { 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 Model modelData;
protected final ArrayList<D> data = new ArrayList<>(); protected final ArrayList<D> data = new ArrayList<>();
protected boolean anyToRemove; protected boolean anyToRemove;
protected AbstractInstancer(StructType<D> type, Model modelData) { protected AbstractInstancer(Supplier<D> type, Model modelData) {
this.type = type; this.type = type;
this.modelData = modelData; this.modelData = modelData;
} }
@ -26,7 +27,7 @@ public abstract class AbstractInstancer<D extends InstanceData> implements Insta
*/ */
@Override @Override
public D createInstance() { 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.InstanceData;
import com.jozufozu.flywheel.api.Instancer; import com.jozufozu.flywheel.api.Instancer;
import com.jozufozu.flywheel.api.Material; 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.jozufozu.flywheel.core.model.Model;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer; 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> { public class BatchedMaterial<D extends InstanceData> implements Material<D> {
protected final Map<Object, CPUInstancer<D>> models; 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.type = type;
this.models = new HashMap<>(); 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.InstanceData;
import com.jozufozu.flywheel.api.MaterialGroup; import com.jozufozu.flywheel.api.MaterialGroup;
import com.jozufozu.flywheel.api.struct.Batched;
import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.backend.instancing.TaskEngine; import com.jozufozu.flywheel.backend.instancing.TaskEngine;
import com.jozufozu.flywheel.backend.model.DirectBufferBuilder; import com.jozufozu.flywheel.backend.model.DirectBufferBuilder;
@ -19,7 +20,7 @@ public class BatchedMaterialGroup implements MaterialGroup {
protected final RenderType state; 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) { public BatchedMaterialGroup(RenderType state) {
this.state = state; this.state = state;
@ -27,8 +28,12 @@ public class BatchedMaterialGroup implements MaterialGroup {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public <D extends InstanceData> BatchedMaterial<D> material(StructType<D> spec) { public <D extends InstanceData> BatchedMaterial<D> material(StructType<D> type) {
return (BatchedMaterial<D>) materials.computeIfAbsent(spec, BatchedMaterial::new); 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) { 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); stack.translate(-event.camX, -event.camY, -event.camZ);
for (Map.Entry<RenderType, BatchedMaterialGroup> entry : layers.get(event.getLayer()).entrySet()) { for (BatchedMaterialGroup group : layers.get(event.getLayer()).values()) {
BatchedMaterialGroup group = entry.getValue();
group.render(stack, buffers, taskEngine); group.render(stack, buffers, taskEngine);
} }

View file

@ -1,7 +1,7 @@
package com.jozufozu.flywheel.backend.instancing.batching; package com.jozufozu.flywheel.backend.instancing.batching;
import com.jozufozu.flywheel.api.InstanceData; 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.api.struct.StructType;
import com.jozufozu.flywheel.backend.instancing.AbstractInstancer; import com.jozufozu.flywheel.backend.instancing.AbstractInstancer;
import com.jozufozu.flywheel.backend.instancing.TaskEngine; 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> { 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 sbb;
private final ModelTransformer.Params defaultParams; private final ModelTransformer.Params defaultParams;
public CPUInstancer(StructType<D> type, Model modelData) { public CPUInstancer(Batched<D> type, Model modelData) {
super(type, modelData); super(type::create, modelData);
batchingType = type;
sbb = new ModelTransformer(modelData); sbb = new ModelTransformer(modelData);
defaultParams = ModelTransformer.Params.defaultParams(); 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) { 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(); ModelTransformer.Params params = defaultParams.copy();
for (D d : data.subList(from, to)) { for (D d : data.subList(from, to)) {
transform.transform(d, params); batchingType.transform(d, params);
sbb.renderInto(params, stack, buffer); sbb.renderInto(params, stack, buffer);
@ -67,7 +62,7 @@ public class CPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
void drawAll(PoseStack stack, VertexConsumer buffer) { void drawAll(PoseStack stack, VertexConsumer buffer) {
ModelTransformer.Params params = defaultParams.copy(); ModelTransformer.Params params = defaultParams.copy();
for (D d : data) { for (D d : data) {
transform.transform(d, params); batchingType.transform(d, params);
sbb.renderInto(params, stack, buffer); sbb.renderInto(params, stack, buffer);

View file

@ -4,6 +4,7 @@ import java.util.BitSet;
import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.InstanceData; 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.StructType;
import com.jozufozu.flywheel.api.struct.StructWriter; import com.jozufozu.flywheel.api.struct.StructWriter;
import com.jozufozu.flywheel.backend.Backend; 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 ModelAllocator modelAllocator;
private final VertexFormat instanceFormat; private final VertexFormat instanceFormat;
private final Instanced<D> instancedType;
private IBufferedModel model; private IBufferedModel model;
private GlVertexArray vao; private GlVertexArray vao;
@ -34,10 +36,11 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
protected boolean anyToUpdate; protected boolean anyToUpdate;
public GPUInstancer(StructType<D> type, Model model, ModelAllocator modelAllocator) { public GPUInstancer(Instanced<D> type, Model model, ModelAllocator modelAllocator) {
super(type, model); super(type::create, model);
this.modelAllocator = modelAllocator; this.modelAllocator = modelAllocator;
this.instanceFormat = type.format(); this.instanceFormat = type.format();
instancedType = type;
} }
@Override @Override
@ -152,8 +155,7 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
try (MappedBuffer mapped = instanceVBO.getBuffer(0, glBufferSize)) { try (MappedBuffer mapped = instanceVBO.getBuffer(0, glBufferSize)) {
final StructWriter<D> writer = type.asInstanced() final StructWriter<D> writer = instancedType.getWriter(mapped);
.getWriter(mapped);
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
final D element = data.get(i); final D element = data.get(i);
@ -176,8 +178,7 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
instanceVBO.alloc(glBufferSize); instanceVBO.alloc(glBufferSize);
try (MappedBuffer buffer = instanceVBO.getBuffer(0, glBufferSize)) { try (MappedBuffer buffer = instanceVBO.getBuffer(0, glBufferSize)) {
StructWriter<D> writer = type.asInstanced() StructWriter<D> writer = instancedType.getWriter(buffer);
.getWriter(buffer);
for (D datum : data) { for (D datum : data) {
writer.write(datum); 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.InstanceData;
import com.jozufozu.flywheel.api.Instancer; import com.jozufozu.flywheel.api.Instancer;
import com.jozufozu.flywheel.api.Material; 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.Backend;
import com.jozufozu.flywheel.backend.RenderWork; import com.jozufozu.flywheel.backend.RenderWork;
import com.jozufozu.flywheel.backend.model.ImmediateAllocator; import com.jozufozu.flywheel.backend.model.ImmediateAllocator;
@ -25,10 +25,10 @@ public class InstancedMaterial<D extends InstanceData> implements Material<D> {
final ModelAllocator allocator; final ModelAllocator allocator;
protected final Cache<Object, GPUInstancer<D>> models; protected final Cache<Object, GPUInstancer<D>> models;
protected final StructType<D> type; protected final Instanced<D> type;
public InstancedMaterial(StructType<D> spec) { public InstancedMaterial(Instanced<D> type) {
this.type = spec; this.type = type;
if (Backend.getInstance().compat.onAMDWindows()) { if (Backend.getInstance().compat.onAMDWindows()) {
allocator = ImmediateAllocator.INSTANCE; allocator = ImmediateAllocator.INSTANCE;

View file

@ -6,6 +6,7 @@ import java.util.Map;
import com.jozufozu.flywheel.api.InstanceData; import com.jozufozu.flywheel.api.InstanceData;
import com.jozufozu.flywheel.api.MaterialGroup; import com.jozufozu.flywheel.api.MaterialGroup;
import com.jozufozu.flywheel.api.struct.Instanced;
import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.backend.model.ModelPool; import com.jozufozu.flywheel.backend.model.ModelPool;
import com.jozufozu.flywheel.core.shader.WorldProgram; 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 InstancingEngine<P> owner;
protected final RenderType type; 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) { public InstancedMaterialGroup(InstancingEngine<P> owner, RenderType type) {
this.owner = owner; this.owner = owner;
@ -34,8 +35,12 @@ public class InstancedMaterialGroup<P extends WorldProgram> implements MaterialG
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public <D extends InstanceData> InstancedMaterial<D> material(StructType<D> spec) { public <D extends InstanceData> InstancedMaterial<D> material(StructType<D> type) {
return (InstancedMaterial<D>) materials.computeIfAbsent(spec, InstancedMaterial::new); 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) { 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) { 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(); InstancedMaterial<?> material = entry.getValue();
if (material.nothingToRender()) continue; if (material.nothingToRender()) continue;
@ -61,7 +66,6 @@ public class InstancedMaterialGroup<P extends WorldProgram> implements MaterialG
} }
P program = owner.getProgram(entry.getKey() P program = owner.getProgram(entry.getKey()
.asInstanced()
.getProgramSpec()).get(); .getProgramSpec()).get();
program.bind(); program.bind();

View file

@ -109,6 +109,7 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
} }
private Stream<InstancedMaterialGroup<P>> getGroupsToRender(@Nullable RenderLayer layer) { private Stream<InstancedMaterialGroup<P>> getGroupsToRender(@Nullable RenderLayer layer) {
// layer is null when this is called from CrumblingRenderer
if (layer != null) { if (layer != null) {
return layers.get(layer) return layers.get(layer)
.values() .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.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Stream; import java.util.stream.Stream;
import com.jozufozu.flywheel.api.struct.Instanced;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.ShaderContext; import com.jozufozu.flywheel.backend.ShaderContext;
import com.jozufozu.flywheel.backend.pipeline.ShaderPipeline; import com.jozufozu.flywheel.backend.pipeline.ShaderPipeline;
@ -87,8 +89,9 @@ public class WorldContext<P extends WorldProgram> implements ShaderContext<P> {
if (specStream == null) { if (specStream == null) {
specStream = () -> backend.allMaterials() specStream = () -> backend.allMaterials()
.stream() .stream()
.map(type -> type.asInstanced() .map(t -> t instanceof Instanced<?> i ? i : null)
.getProgramSpec()); .filter(Objects::nonNull)
.map(Instanced::getProgramSpec);
} }
return new WorldContext<>(backend, name, specStream, pipeline); return new WorldContext<>(backend, name, specStream, pipeline);
} }

View file

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

View file

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