Batched simplification

- Perform various cleanup in batching code
- Remove ClientLevel argument from InstanceVertexTransformer#transform
- Rename Plan#maybeSimplify to simplify
- Rename some classes
- Move TickContext from impl to impl.visualization
- Move VertexListProviderRegistryImpl from impl to impl.vertex
This commit is contained in:
PepperCode1 2023-05-28 09:54:51 -07:00
parent afb14bc1f6
commit 961fafce0d
33 changed files with 172 additions and 169 deletions

View file

@ -12,6 +12,7 @@ import net.minecraft.client.Camera;
import net.minecraft.core.Vec3i; import net.minecraft.core.Vec3i;
public interface Engine extends InstancerProvider { public interface Engine extends InstancerProvider {
Plan<RenderContext> createFramePlan();
void renderStage(TaskExecutor executor, RenderContext context, RenderStage stage); void renderStage(TaskExecutor executor, RenderContext context, RenderStage stage);
@ -28,6 +29,4 @@ public interface Engine extends InstancerProvider {
void addDebugInfo(List<String> info); void addDebugInfo(List<String> info);
void delete(); void delete();
Plan<RenderContext> createFramePlan();
} }

View file

@ -2,8 +2,6 @@ package com.jozufozu.flywheel.api.instance;
import com.jozufozu.flywheel.api.vertex.MutableVertexList; import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import net.minecraft.client.multiplayer.ClientLevel;
public interface InstanceVertexTransformer<I extends Instance> { public interface InstanceVertexTransformer<I extends Instance> {
void transform(MutableVertexList vertexList, I instance, ClientLevel level); void transform(MutableVertexList vertexList, I instance);
} }

View file

@ -67,5 +67,5 @@ public interface Plan<C> {
* *
* @return A simplified plan, or this. * @return A simplified plan, or this.
*/ */
Plan<C> maybeSimplify(); Plan<C> simplify();
} }

View file

@ -1,6 +1,6 @@
package com.jozufozu.flywheel.api.vertex; package com.jozufozu.flywheel.api.vertex;
import com.jozufozu.flywheel.impl.VertexListProviderRegistryImpl; import com.jozufozu.flywheel.impl.vertex.VertexListProviderRegistryImpl;
import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormat;
public final class VertexListProviderRegistry { public final class VertexListProviderRegistry {

View file

@ -20,5 +20,5 @@ public interface DynamicVisual extends Visual {
* <p> * <p>
* {@link Instancer}/{@link Instance} creation/acquisition is safe here. * {@link Instancer}/{@link Instance} creation/acquisition is safe here.
*/ */
void beginFrame(VisualFrameContext context); void beginFrame(VisualFrameContext ctx);
} }

View file

@ -27,5 +27,5 @@ public interface TickableVisual extends Visual {
* <p> * <p>
* {@link Instancer}/{@link Instance} creation/acquisition is safe here. * {@link Instancer}/{@link Instance} creation/acquisition is safe here.
*/ */
void tick(VisualTickContext c); void tick(VisualTickContext ctx);
} }

View file

@ -12,7 +12,7 @@ import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
public record BatchContext(ClientLevel level, PoseStack.Pose matrices, FrustumIntersection frustum) { public record BatchContext(FrustumIntersection frustum, ClientLevel level, PoseStack.Pose matrices) {
@NotNull @NotNull
static BatchContext create(RenderContext context, BlockPos origin) { static BatchContext create(RenderContext context, BlockPos origin) {
Vec3 cameraPos = context.camera() Vec3 cameraPos = context.camera()
@ -23,6 +23,6 @@ public record BatchContext(ClientLevel level, PoseStack.Pose matrices, FrustumIn
org.joml.Matrix4f proj = MatrixUtil.toJoml(context.viewProjection()); org.joml.Matrix4f proj = MatrixUtil.toJoml(context.viewProjection());
proj.translate((float) (origin.getX() - cameraPos.x), (float) (origin.getY() - cameraPos.y), (float) (origin.getZ() - cameraPos.z)); proj.translate((float) (origin.getX() - cameraPos.x), (float) (origin.getY() - cameraPos.y), (float) (origin.getZ() - cameraPos.z));
return new BatchContext(context.level(), stack.last(), new FrustumIntersection(proj)); return new BatchContext(new FrustumIntersection(proj), context.level(), stack.last());
} }
} }

View file

@ -7,12 +7,9 @@ import java.util.Set;
import com.jozufozu.flywheel.api.event.RenderStage; import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.extension.BufferBuilderExtension; import com.jozufozu.flywheel.extension.BufferBuilderExtension;
import com.jozufozu.flywheel.extension.RenderTypeExtension;
import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.BufferBuilder;
import net.minecraft.client.renderer.RenderType; public class BatchedDrawTracker {
public class BatchingDrawTracker {
private final Map<RenderStage, Set<DrawBuffer>> activeBuffers = new EnumMap<>(RenderStage.class); private final Map<RenderStage, Set<DrawBuffer>> activeBuffers = new EnumMap<>(RenderStage.class);
{ {
for (RenderStage stage : RenderStage.values()) { for (RenderStage stage : RenderStage.values()) {
@ -22,31 +19,33 @@ public class BatchingDrawTracker {
private final BufferBuilder scratch; private final BufferBuilder scratch;
public BatchingDrawTracker() { public BatchedDrawTracker() {
scratch = new BufferBuilder(8); scratch = new BufferBuilder(8);
((BufferBuilderExtension) scratch).flywheel$freeBuffer(); ((BufferBuilderExtension) scratch).flywheel$freeBuffer();
} }
public static DrawBuffer getBuffer(RenderType renderType, RenderStage stage) { public void markActive(DrawBuffer buffer) {
return RenderTypeExtension.getDrawBufferSet(renderType)
.getBuffer(stage);
}
public void markActive(RenderStage stage, DrawBuffer buffer) {
synchronized (activeBuffers) { synchronized (activeBuffers) {
activeBuffers.get(stage) activeBuffers.get(buffer.getRenderStage())
.add(buffer); .add(buffer);
} }
} }
public void markInactive(RenderStage stage, DrawBuffer buffer) { public void markInactive(DrawBuffer buffer) {
synchronized (activeBuffers) { synchronized (activeBuffers) {
activeBuffers.get(stage) activeBuffers.get(buffer.getRenderStage())
.remove(buffer); .remove(buffer);
} }
} }
public boolean hasStage(RenderStage stage) {
synchronized (activeBuffers) {
return !activeBuffers.get(stage)
.isEmpty();
}
}
/** /**
* Draw and reset all DrawBuffers for the given RenderStage. * Draw and reset all DrawBuffers for the given RenderStage.
* *
@ -80,11 +79,4 @@ public class BatchingDrawTracker {
buffers.clear(); buffers.clear();
} }
} }
public boolean hasStage(RenderStage stage) {
synchronized (activeBuffers) {
return !activeBuffers.get(stage)
.isEmpty();
}
}
} }

View file

@ -6,8 +6,8 @@ import com.jozufozu.flywheel.api.instance.Instance;
import com.jozufozu.flywheel.api.instance.InstanceType; import com.jozufozu.flywheel.api.instance.InstanceType;
import com.jozufozu.flywheel.backend.engine.AbstractInstancer; import com.jozufozu.flywheel.backend.engine.AbstractInstancer;
public class CPUInstancer<I extends Instance> extends AbstractInstancer<I> { public class BatchedInstancer<I extends Instance> extends AbstractInstancer<I> {
public CPUInstancer(InstanceType<I> type) { public BatchedInstancer(InstanceType<I> type) {
super(type); super(type);
} }

View file

@ -6,6 +6,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.joml.Vector4fc;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.Flywheel;
@ -149,9 +150,10 @@ public class BatchedMeshPool {
} }
public class BufferedMesh { public class BufferedMesh {
public final Mesh mesh; private final Mesh mesh;
private final int byteSize; private final int byteSize;
private final int vertexCount; private final int vertexCount;
private final Vector4fc boundingSphere;
private long byteIndex; private long byteIndex;
private boolean deleted; private boolean deleted;
@ -159,6 +161,7 @@ public class BatchedMeshPool {
private BufferedMesh(Mesh mesh, long byteIndex) { private BufferedMesh(Mesh mesh, long byteIndex) {
this.mesh = mesh; this.mesh = mesh;
vertexCount = mesh.getVertexCount(); vertexCount = mesh.getVertexCount();
boundingSphere = mesh.getBoundingSphere();
byteSize = vertexCount * vertexFormat.getVertexSize(); byteSize = vertexCount * vertexFormat.getVertexSize();
this.byteIndex = byteIndex; this.byteIndex = byteIndex;
} }
@ -171,6 +174,10 @@ public class BatchedMeshPool {
return vertexCount; return vertexCount;
} }
public Vector4fc getBoundingSphere() {
return boundingSphere;
}
public VertexFormat getVertexFormat() { public VertexFormat getVertexFormat() {
return vertexFormat; return vertexFormat;
} }

View file

@ -16,39 +16,39 @@ import net.minecraft.client.renderer.RenderType;
/** /**
* All the rendering that happens within a render stage. * All the rendering that happens within a render stage.
*/ */
public class BatchingStage implements SimplyComposedPlan<BatchContext> { public class BatchedStagePlan implements SimplyComposedPlan<BatchContext> {
private final RenderStage stage; private final RenderStage stage;
private final BatchingDrawTracker tracker; private final BatchedDrawTracker tracker;
private final Map<RenderType, BufferPlan> buffers = new HashMap<>(); private final Map<RenderType, BufferPlan> bufferPlans = new HashMap<>();
public BatchingStage(RenderStage renderStage, BatchingDrawTracker tracker) { public BatchedStagePlan(RenderStage renderStage, BatchedDrawTracker tracker) {
stage = renderStage; stage = renderStage;
this.tracker = tracker; this.tracker = tracker;
} }
@Override @Override
public void execute(TaskExecutor taskExecutor, BatchContext context, Runnable onCompletion) { public void execute(TaskExecutor taskExecutor, BatchContext context, Runnable onCompletion) {
if (buffers.isEmpty()) { if (isEmpty()) {
onCompletion.run(); onCompletion.run();
return; return;
} }
taskExecutor.execute(() -> { taskExecutor.execute(() -> {
var sync = new Synchronizer(buffers.size(), onCompletion); var sync = new Synchronizer(bufferPlans.size(), onCompletion);
for (var buffer : buffers.values()) { for (var plan : bufferPlans.values()) {
buffer.execute(taskExecutor, context, sync); plan.execute(taskExecutor, context, sync);
} }
}); });
} }
public void put(RenderType renderType, TransformCall<?> transformCall) { public void put(RenderType renderType, TransformCall<?> transformCall) {
buffers.computeIfAbsent(renderType, type -> new BufferPlan(BatchingDrawTracker.getBuffer(type, stage))) bufferPlans.computeIfAbsent(renderType, type -> new BufferPlan(DrawBuffer.get(type, stage)))
.add(transformCall); .add(transformCall);
} }
public boolean isEmpty() { public boolean isEmpty() {
return buffers.isEmpty(); return bufferPlans.isEmpty();
} }
private class BufferPlan implements SimplyComposedPlan<BatchContext> { private class BufferPlan implements SimplyComposedPlan<BatchContext> {
@ -72,19 +72,17 @@ public class BatchingStage implements SimplyComposedPlan<BatchContext> {
return; return;
} }
tracker.markActive(stage, buffer); tracker.markActive(buffer);
var vertexCounter = new AtomicInteger(0);
buffer.prepare(vertexCount); buffer.prepare(vertexCount);
var vertexCounter = new AtomicInteger(0);
var planContext = new TransformCall.PlanContext(ctx.frustum(), vertexCounter, buffer, ctx.level(), ctx.matrices());
var synchronizer = new Synchronizer(transformCalls.size(), () -> { var synchronizer = new Synchronizer(transformCalls.size(), () -> {
buffer.vertexCount(vertexCounter.get()); buffer.verticesToDraw(vertexCounter.get());
onCompletion.run(); onCompletion.run();
}); });
var planContext = new TransformCall.PlanContext(ctx, buffer, vertexCounter);
for (var transformCall : transformCalls) { for (var transformCall : transformCalls) {
transformCall.plan() transformCall.plan()
.execute(taskExecutor, planContext, synchronizer); .execute(taskExecutor, planContext, synchronizer);

View file

@ -24,11 +24,11 @@ import com.mojang.blaze3d.vertex.VertexFormat;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
public class BatchingEngine extends AbstractEngine implements SimplyComposedPlan<RenderContext> { public class BatchingEngine extends AbstractEngine implements SimplyComposedPlan<RenderContext> {
private final BatchingDrawTracker drawTracker = new BatchingDrawTracker(); private final BatchedDrawTracker drawTracker = new BatchedDrawTracker();
private final Map<InstancerKey<?>, CPUInstancer<?>> instancers = new HashMap<>(); private final Map<InstancerKey<?>, BatchedInstancer<?>> instancers = new HashMap<>();
private final List<UninitializedInstancer> uninitializedInstancers = new ArrayList<>(); private final List<UninitializedInstancer> uninitializedInstancers = new ArrayList<>();
private final List<CPUInstancer<?>> initializedInstancers = new ArrayList<>(); private final List<BatchedInstancer<?>> initializedInstancers = new ArrayList<>();
private final Map<RenderStage, BatchingStage> stages = new EnumMap<>(RenderStage.class); private final Map<RenderStage, BatchedStagePlan> stagePlans = new EnumMap<>(RenderStage.class);
private final Map<VertexFormat, BatchedMeshPool> meshPools = new HashMap<>(); private final Map<VertexFormat, BatchedMeshPool> meshPools = new HashMap<>();
public BatchingEngine(int maxOriginDistance) { public BatchingEngine(int maxOriginDistance) {
@ -36,8 +36,16 @@ public class BatchingEngine extends AbstractEngine implements SimplyComposedPlan
} }
@Override @Override
@SuppressWarnings("unchecked")
public <I extends Instance> Instancer<I> instancer(InstanceType<I> type, Model model, RenderStage stage) { public <I extends Instance> Instancer<I> instancer(InstanceType<I> type, Model model, RenderStage stage) {
return this.getInstancer(type, model, stage); InstancerKey<I> key = new InstancerKey<>(type, model, stage);
BatchedInstancer<I> instancer = (BatchedInstancer<I>) instancers.get(key);
if (instancer == null) {
instancer = new BatchedInstancer<>(type);
instancers.put(key, instancer);
uninitializedInstancers.add(new UninitializedInstancer(instancer, model, stage));
}
return instancer;
} }
@Override @Override
@ -46,11 +54,11 @@ public class BatchingEngine extends AbstractEngine implements SimplyComposedPlan
BatchContext ctx = BatchContext.create(context, renderOrigin); BatchContext ctx = BatchContext.create(context, renderOrigin);
var sync = new Synchronizer(stages.values() var sync = new Synchronizer(stagePlans.values()
.size(), onCompletion); .size(), onCompletion);
for (var transformSet : stages.values()) { for (var stagePlan : stagePlans.values()) {
transformSet.execute(taskExecutor, ctx, sync); stagePlan.execute(taskExecutor, ctx, sync);
} }
} }
@ -67,7 +75,7 @@ public class BatchingEngine extends AbstractEngine implements SimplyComposedPlan
@Override @Override
protected void onRenderOriginChanged() { protected void onRenderOriginChanged() {
initializedInstancers.forEach(CPUInstancer::clear); initializedInstancers.forEach(BatchedInstancer::clear);
} }
@Override @Override
@ -87,18 +95,6 @@ public class BatchingEngine extends AbstractEngine implements SimplyComposedPlan
info.add("Origin: " + renderOrigin.getX() + ", " + renderOrigin.getY() + ", " + renderOrigin.getZ()); info.add("Origin: " + renderOrigin.getX() + ", " + renderOrigin.getY() + ", " + renderOrigin.getZ());
} }
@SuppressWarnings("unchecked")
public <I extends Instance> Instancer<I> getInstancer(InstanceType<I> type, Model model, RenderStage stage) {
InstancerKey<I> key = new InstancerKey<>(type, model, stage);
CPUInstancer<I> instancer = (CPUInstancer<I>) instancers.get(key);
if (instancer == null) {
instancer = new CPUInstancer<>(type);
instancers.put(key, instancer);
uninitializedInstancers.add(new UninitializedInstancer(instancer, model, stage));
}
return instancer;
}
private void flush() { private void flush() {
for (var instancer : uninitializedInstancers) { for (var instancer : uninitializedInstancers) {
add(instancer.instancer(), instancer.model(), instancer.stage()); add(instancer.instancer(), instancer.model(), instancer.stage());
@ -110,14 +106,14 @@ public class BatchingEngine extends AbstractEngine implements SimplyComposedPlan
} }
} }
private void add(CPUInstancer<?> instancer, Model model, RenderStage stage) { private void add(BatchedInstancer<?> instancer, Model model, RenderStage stage) {
var batchingStage = stages.computeIfAbsent(stage, renderStage -> new BatchingStage(renderStage, drawTracker)); var stagePlan = stagePlans.computeIfAbsent(stage, renderStage -> new BatchedStagePlan(renderStage, drawTracker));
var meshes = model.getMeshes(); var meshes = model.getMeshes();
for (var entry : meshes.entrySet()) { for (var entry : meshes.entrySet()) {
var material = entry.getKey(); var material = entry.getKey();
RenderType renderType = material.getBatchingRenderType(); RenderType renderType = material.getBatchingRenderType();
var transformCall = new TransformCall<>(instancer, material, alloc(entry.getValue(), renderType.format())); var transformCall = new TransformCall<>(instancer, material, alloc(entry.getValue(), renderType.format()));
batchingStage.put(renderType, transformCall); stagePlan.put(renderType, transformCall);
} }
initializedInstancers.add(instancer); initializedInstancers.add(instancer);
} }
@ -127,6 +123,6 @@ public class BatchingEngine extends AbstractEngine implements SimplyComposedPlan
.alloc(mesh); .alloc(mesh);
} }
private record UninitializedInstancer(CPUInstancer<?> instancer, Model model, RenderStage stage) { private record UninitializedInstancer(BatchedInstancer<?> instancer, Model model, RenderStage stage) {
} }
} }

View file

@ -5,9 +5,11 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.jozufozu.flywheel.api.event.ReloadRenderersEvent; import com.jozufozu.flywheel.api.event.ReloadRenderersEvent;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.vertex.ReusableVertexList; import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
import com.jozufozu.flywheel.api.vertex.VertexListProvider; import com.jozufozu.flywheel.api.vertex.VertexListProvider;
import com.jozufozu.flywheel.extension.BufferBuilderExtension; import com.jozufozu.flywheel.extension.BufferBuilderExtension;
import com.jozufozu.flywheel.extension.RenderTypeExtension;
import com.jozufozu.flywheel.lib.memory.MemoryBlock; import com.jozufozu.flywheel.lib.memory.MemoryBlock;
import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormat;
@ -22,6 +24,7 @@ public class DrawBuffer {
private static final List<DrawBuffer> ALL = new ArrayList<>(); private static final List<DrawBuffer> ALL = new ArrayList<>();
private final RenderType renderType; private final RenderType renderType;
private final RenderStage renderStage;
private final VertexFormat format; private final VertexFormat format;
private final int stride; private final int stride;
private final VertexListProvider provider; private final VertexListProvider provider;
@ -31,9 +34,11 @@ public class DrawBuffer {
private boolean prepared; private boolean prepared;
private int vertexCount; private int vertexCount;
private int verticesToDraw;
public DrawBuffer(RenderType renderType, VertexFormat format, int stride, VertexListProvider provider) { public DrawBuffer(RenderType renderType, RenderStage renderStage, VertexFormat format, int stride, VertexListProvider provider) {
this.renderType = renderType; this.renderType = renderType;
this.renderStage = renderStage;
this.format = format; this.format = format;
this.stride = stride; this.stride = stride;
this.provider = provider; this.provider = provider;
@ -52,6 +57,7 @@ public class DrawBuffer {
} }
this.vertexCount = vertexCount; this.vertexCount = vertexCount;
verticesToDraw = this.vertexCount;
// Add one extra vertex to uphold the vanilla assumption that BufferBuilders have at least // Add one extra vertex to uphold the vanilla assumption that BufferBuilders have at least
// enough buffer space for one more vertex. Rubidium checks for this extra space when popNextBuffer // enough buffer space for one more vertex. Rubidium checks for this extra space when popNextBuffer
@ -69,15 +75,15 @@ public class DrawBuffer {
prepared = true; prepared = true;
} }
public void vertexCount(int vertexCount) {
this.vertexCount = vertexCount;
}
public ReusableVertexList slice(int startVertex, int vertexCount) { public ReusableVertexList slice(int startVertex, int vertexCount) {
if (!prepared) { if (!prepared) {
throw new IllegalStateException("Cannot slice DrawBuffer that is not prepared!"); throw new IllegalStateException("Cannot slice DrawBuffer that is not prepared!");
} }
if (startVertex + vertexCount > this.vertexCount) {
throw new IndexOutOfBoundsException("Vertex count greater than allocated: " + startVertex + " + " + vertexCount + " > " + this.vertexCount);
}
ReusableVertexList vertexList = provider.createVertexList(); ReusableVertexList vertexList = provider.createVertexList();
vertexList.ptr(ptrForVertex(startVertex)); vertexList.ptr(ptrForVertex(startVertex));
vertexList.vertexCount(vertexCount); vertexList.vertexCount(vertexCount);
@ -88,6 +94,10 @@ public class DrawBuffer {
return memory.ptr() + startVertex * stride; return memory.ptr() + startVertex * stride;
} }
public void verticesToDraw(int verticesToDraw) {
this.verticesToDraw = verticesToDraw;
}
/** /**
* Injects the backing buffer into the given builder and prepares it for rendering. * Injects the backing buffer into the given builder and prepares it for rendering.
* *
@ -99,13 +109,17 @@ public class DrawBuffer {
} }
buffer.clear(); buffer.clear();
bufferBuilder.flywheel$injectForRender(buffer, format, vertexCount); bufferBuilder.flywheel$injectForRender(buffer, format, verticesToDraw);
} }
public RenderType getRenderType() { public RenderType getRenderType() {
return renderType; return renderType;
} }
public RenderStage getRenderStage() {
return renderStage;
}
public VertexFormat getVertexFormat() { public VertexFormat getVertexFormat() {
return format; return format;
} }
@ -118,11 +132,15 @@ public class DrawBuffer {
return vertexCount; return vertexCount;
} }
public int getVerticesToDraw() {
return verticesToDraw;
}
/** /**
* @return {@code true} if the buffer has any vertices. * @return {@code true} if the buffer has any vertices to draw.
*/ */
public boolean hasVertices() { public boolean hasVertices() {
return vertexCount > 0; return verticesToDraw > 0;
} }
/** /**
@ -133,6 +151,7 @@ public class DrawBuffer {
public void reset() { public void reset() {
prepared = false; prepared = false;
vertexCount = 0; vertexCount = 0;
verticesToDraw = 0;
} }
public void free() { public void free() {
@ -150,4 +169,9 @@ public class DrawBuffer {
public static void onReloadRenderers(ReloadRenderersEvent event) { public static void onReloadRenderers(ReloadRenderersEvent event) {
ALL.forEach(DrawBuffer::free); ALL.forEach(DrawBuffer::free);
} }
public static DrawBuffer get(RenderType renderType, RenderStage stage) {
return RenderTypeExtension.getDrawBufferSet(renderType)
.getBuffer(stage);
}
} }

View file

@ -25,6 +25,6 @@ public class DrawBufferSet {
} }
public DrawBuffer getBuffer(RenderStage stage) { public DrawBuffer getBuffer(RenderStage stage) {
return buffers.computeIfAbsent(stage, $ -> new DrawBuffer(renderType, format, stride, provider)); return buffers.computeIfAbsent(stage, renderStage -> new DrawBuffer(renderType, renderStage, format, stride, provider));
} }
} }

View file

@ -2,6 +2,7 @@ package com.jozufozu.flywheel.backend.engine.batching;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import org.joml.FrustumIntersection;
import org.joml.Vector4f; import org.joml.Vector4f;
import org.joml.Vector4fc; import org.joml.Vector4fc;
@ -18,61 +19,51 @@ import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Matrix3f; import com.mojang.math.Matrix3f;
import com.mojang.math.Matrix4f; import com.mojang.math.Matrix4f;
import net.minecraft.client.multiplayer.ClientLevel;
public class TransformCall<I extends Instance> { public class TransformCall<I extends Instance> {
private final CPUInstancer<I> instancer; private final BatchedInstancer<I> instancer;
private final int meshVertexCount; private final int meshVertexCount;
private final InstanceVertexTransformer<I> instanceVertexTransformer;
private final MaterialVertexTransformer materialVertexTransformer;
private final InstanceBoundingSphereTransformer<I> boundingSphereTransformer;
private final Vector4fc boundingSphere;
private final Plan<PlanContext> drawPlan; private final Plan<PlanContext> drawPlan;
public TransformCall(CPUInstancer<I> instancer, Material material, BatchedMeshPool.BufferedMesh mesh) { public TransformCall(BatchedInstancer<I> instancer, Material material, BatchedMeshPool.BufferedMesh mesh) {
this.instancer = instancer; this.instancer = instancer;
instanceVertexTransformer = instancer.type.getVertexTransformer(); InstanceVertexTransformer<I> instanceVertexTransformer = instancer.type.getVertexTransformer();
boundingSphereTransformer = instancer.type.getBoundingSphereTransformer(); InstanceBoundingSphereTransformer<I> boundingSphereTransformer = instancer.type.getBoundingSphereTransformer();
materialVertexTransformer = material.getVertexTransformer(); MaterialVertexTransformer materialVertexTransformer = material.getVertexTransformer();
meshVertexCount = mesh.getVertexCount(); meshVertexCount = mesh.getVertexCount();
boundingSphere = mesh.mesh.getBoundingSphere(); Vector4fc meshBoundingSphere = mesh.getBoundingSphere();
drawPlan = ForEachPlan.of(instancer::getAll, (instance, ctx) -> { drawPlan = ForEachPlan.of(instancer::getAll, (instance, ctx) -> {
var boundingSphere = new Vector4f(this.boundingSphere); var boundingSphere = new Vector4f(meshBoundingSphere);
boundingSphereTransformer.transform(boundingSphere, instance); boundingSphereTransformer.transform(boundingSphere, instance);
if (!ctx.ctx.frustum() if (!ctx.frustum
.testSphere(boundingSphere.x, boundingSphere.y, boundingSphere.z, boundingSphere.w)) { .testSphere(boundingSphere.x, boundingSphere.y, boundingSphere.z, boundingSphere.w)) {
return; return;
} }
final int baseVertex = ctx.vertexCount.getAndAdd(meshVertexCount); final int baseVertex = ctx.vertexCounter.getAndAdd(meshVertexCount);
if (baseVertex + meshVertexCount > ctx.buffer.getVertexCount()) {
throw new IndexOutOfBoundsException("Vertex count greater than allocated: " + baseVertex + " + " + meshVertexCount + " > " + ctx.buffer.getVertexCount());
}
var sub = ctx.buffer.slice(baseVertex, meshVertexCount); var sub = ctx.buffer.slice(baseVertex, meshVertexCount);
mesh.copyTo(sub.ptr()); mesh.copyTo(sub.ptr());
instanceVertexTransformer.transform(sub, instance);
instanceVertexTransformer.transform(sub, instance, ctx.ctx.level()); materialVertexTransformer.transform(sub, ctx.level);
applyMatrices(sub, ctx.matrices);
materialVertexTransformer.transform(sub, ctx.ctx.level());
applyMatrices(sub, ctx.ctx.matrices());
}); });
} }
public int getTotalVertexCount() {
return meshVertexCount * instancer.getInstanceCount();
}
public void setup() { public void setup() {
instancer.update(); instancer.update();
} }
public int getTotalVertexCount() {
return meshVertexCount * instancer.getInstanceCount();
}
public Plan<PlanContext> plan() { public Plan<PlanContext> plan() {
return drawPlan; return drawPlan;
} }
@ -87,6 +78,6 @@ public class TransformCall<I extends Instance> {
} }
} }
public record PlanContext(BatchContext ctx, DrawBuffer buffer, AtomicInteger vertexCount) { public record PlanContext(FrustumIntersection frustum, AtomicInteger vertexCounter, DrawBuffer buffer, ClientLevel level, PoseStack.Pose matrices) {
} }
} }

View file

@ -3,13 +3,13 @@ package com.jozufozu.flywheel.backend.engine.instancing;
import com.jozufozu.flywheel.gl.array.GlVertexArray; import com.jozufozu.flywheel.gl.array.GlVertexArray;
public class DrawCall { public class DrawCall {
private final GPUInstancer<?> instancer; private final InstancedInstancer<?> instancer;
private final InstancedMeshPool.BufferedMesh mesh; private final InstancedMeshPool.BufferedMesh mesh;
private final int meshAttributes; private final int meshAttributes;
private GlVertexArray vao; private GlVertexArray vao;
public DrawCall(GPUInstancer<?> instancer, InstancedMeshPool.BufferedMesh mesh) { public DrawCall(InstancedInstancer<?> instancer, InstancedMeshPool.BufferedMesh mesh) {
this.instancer = instancer; this.instancer = instancer;
this.mesh = mesh; this.mesh = mesh;

View file

@ -22,10 +22,10 @@ import com.jozufozu.flywheel.api.model.Model;
import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.backend.engine.InstancerKey; import com.jozufozu.flywheel.backend.engine.InstancerKey;
public class InstancingDrawManager { public class InstancedDrawManager {
private final Map<InstancerKey<?>, GPUInstancer<?>> instancers = new HashMap<>(); private final Map<InstancerKey<?>, InstancedInstancer<?>> instancers = new HashMap<>();
private final List<UninitializedInstancer> uninitializedInstancers = new ArrayList<>(); private final List<UninitializedInstancer> uninitializedInstancers = new ArrayList<>();
private final List<GPUInstancer<?>> initializedInstancers = new ArrayList<>(); private final List<InstancedInstancer<?>> initializedInstancers = new ArrayList<>();
private final Map<RenderStage, DrawSet> drawSets = new EnumMap<>(RenderStage.class); private final Map<RenderStage, DrawSet> drawSets = new EnumMap<>(RenderStage.class);
private final Map<VertexType, InstancedMeshPool> meshPools = new HashMap<>(); private final Map<VertexType, InstancedMeshPool> meshPools = new HashMap<>();
@ -36,9 +36,9 @@ public class InstancingDrawManager {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <I extends Instance> Instancer<I> getInstancer(InstanceType<I> type, Model model, RenderStage stage) { public <I extends Instance> Instancer<I> getInstancer(InstanceType<I> type, Model model, RenderStage stage) {
InstancerKey<I> key = new InstancerKey<>(type, model, stage); InstancerKey<I> key = new InstancerKey<>(type, model, stage);
GPUInstancer<I> instancer = (GPUInstancer<I>) instancers.get(key); InstancedInstancer<I> instancer = (InstancedInstancer<I>) instancers.get(key);
if (instancer == null) { if (instancer == null) {
instancer = new GPUInstancer<>(type); instancer = new InstancedInstancer<>(type);
instancers.put(key, instancer); instancers.put(key, instancer);
uninitializedInstancers.add(new UninitializedInstancer(instancer, model, stage)); uninitializedInstancers.add(new UninitializedInstancer(instancer, model, stage));
} }
@ -67,15 +67,15 @@ public class InstancingDrawManager {
.forEach(DrawSet::delete); .forEach(DrawSet::delete);
drawSets.clear(); drawSets.clear();
initializedInstancers.forEach(GPUInstancer::delete); initializedInstancers.forEach(InstancedInstancer::delete);
initializedInstancers.clear(); initializedInstancers.clear();
} }
public void clearInstancers() { public void clearInstancers() {
initializedInstancers.forEach(GPUInstancer::clear); initializedInstancers.forEach(InstancedInstancer::clear);
} }
private void add(GPUInstancer<?> instancer, Model model, RenderStage stage) { private void add(InstancedInstancer<?> instancer, Model model, RenderStage stage) {
instancer.init(); instancer.init();
DrawSet drawSet = drawSets.computeIfAbsent(stage, DrawSet::new); DrawSet drawSet = drawSets.computeIfAbsent(stage, DrawSet::new);
var meshes = model.getMeshes(); var meshes = model.getMeshes();
@ -129,6 +129,6 @@ public class InstancingDrawManager {
} }
} }
private record UninitializedInstancer(GPUInstancer<?> instancer, Model model, RenderStage stage) { private record UninitializedInstancer(InstancedInstancer<?> instancer, Model model, RenderStage stage) {
} }
} }

View file

@ -14,14 +14,14 @@ import com.jozufozu.flywheel.gl.buffer.GlBuffer;
import com.jozufozu.flywheel.gl.buffer.GlBufferUsage; import com.jozufozu.flywheel.gl.buffer.GlBufferUsage;
import com.jozufozu.flywheel.gl.buffer.MappedBuffer; import com.jozufozu.flywheel.gl.buffer.MappedBuffer;
public class GPUInstancer<I extends Instance> extends AbstractInstancer<I> { public class InstancedInstancer<I extends Instance> extends AbstractInstancer<I> {
private final BufferLayout instanceFormat; private final BufferLayout instanceFormat;
private final int instanceStride; private final int instanceStride;
private final Set<GlVertexArray> boundTo = new HashSet<>(); private final Set<GlVertexArray> boundTo = new HashSet<>();
private GlBuffer vbo; private GlBuffer vbo;
public GPUInstancer(InstanceType<I> type) { public InstancedInstancer(InstanceType<I> type) {
super(type); super(type);
instanceFormat = type.getLayout(); instanceFormat = type.getLayout();
instanceStride = instanceFormat.getStride(); instanceStride = instanceFormat.getStride();

View file

@ -26,7 +26,7 @@ import net.minecraft.client.Minecraft;
public class InstancingEngine extends AbstractEngine { public class InstancingEngine extends AbstractEngine {
private final Context context; private final Context context;
private final InstancingDrawManager drawManager = new InstancingDrawManager(); private final InstancedDrawManager drawManager = new InstancedDrawManager();
public InstancingEngine(int maxOriginDistance, Context context) { public InstancingEngine(int maxOriginDistance, Context context) {
super(maxOriginDistance); super(maxOriginDistance);
@ -77,7 +77,7 @@ public class InstancingEngine extends AbstractEngine {
RenderSystem.enableCull(); RenderSystem.enableCull();
} }
private void render(InstancingDrawManager.DrawSet drawSet) { private void render(InstancedDrawManager.DrawSet drawSet) {
for (var entry : drawSet) { for (var entry : drawSet) {
var shader = entry.getKey(); var shader = entry.getKey();
var drawCalls = entry.getValue(); var drawCalls = entry.getValue();

View file

@ -1,8 +1,7 @@
package com.jozufozu.flywheel.impl; package com.jozufozu.flywheel.impl.vertex;
import com.jozufozu.flywheel.api.vertex.VertexListProvider; import com.jozufozu.flywheel.api.vertex.VertexListProvider;
import com.jozufozu.flywheel.extension.VertexFormatExtension; import com.jozufozu.flywheel.extension.VertexFormatExtension;
import com.jozufozu.flywheel.impl.vertex.InferredVertexListProviderImpl;
import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormat;
// TODO: Add freezing // TODO: Add freezing

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.impl; package com.jozufozu.flywheel.impl.visualization;
public record TickContext(double cameraX, double cameraY, double cameraZ) { public record TickContext(double cameraX, double cameraY, double cameraZ) {
} }

View file

@ -17,7 +17,6 @@ import com.jozufozu.flywheel.backend.task.FlwTaskExecutor;
import com.jozufozu.flywheel.backend.task.ParallelTaskExecutor; import com.jozufozu.flywheel.backend.task.ParallelTaskExecutor;
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.impl.TickContext;
import com.jozufozu.flywheel.impl.visualization.manager.BlockEntityVisualManager; import com.jozufozu.flywheel.impl.visualization.manager.BlockEntityVisualManager;
import com.jozufozu.flywheel.impl.visualization.manager.EffectVisualManager; import com.jozufozu.flywheel.impl.visualization.manager.EffectVisualManager;
import com.jozufozu.flywheel.impl.visualization.manager.EntityVisualManager; import com.jozufozu.flywheel.impl.visualization.manager.EntityVisualManager;
@ -59,7 +58,7 @@ public class VisualWorld implements AutoCloseable {
tickPlan = blockEntities.createTickPlan() tickPlan = blockEntities.createTickPlan()
.and(entities.createTickPlan()) .and(entities.createTickPlan())
.and(effects.createTickPlan()) .and(effects.createTickPlan())
.maybeSimplify(); .simplify();
framePlan = new FramePlan(); framePlan = new FramePlan();
} }

View file

@ -7,8 +7,8 @@ import com.jozufozu.flywheel.api.task.Plan;
import com.jozufozu.flywheel.api.visual.VisualFrameContext; import com.jozufozu.flywheel.api.visual.VisualFrameContext;
import com.jozufozu.flywheel.api.visual.VisualTickContext; import com.jozufozu.flywheel.api.visual.VisualTickContext;
import com.jozufozu.flywheel.config.FlwConfig; import com.jozufozu.flywheel.config.FlwConfig;
import com.jozufozu.flywheel.impl.TickContext;
import com.jozufozu.flywheel.impl.visualization.FrameContext; import com.jozufozu.flywheel.impl.visualization.FrameContext;
import com.jozufozu.flywheel.impl.visualization.TickContext;
import com.jozufozu.flywheel.impl.visualization.ratelimit.BandedPrimeLimiter; import com.jozufozu.flywheel.impl.visualization.ratelimit.BandedPrimeLimiter;
import com.jozufozu.flywheel.impl.visualization.ratelimit.DistanceUpdateLimiterImpl; import com.jozufozu.flywheel.impl.visualization.ratelimit.DistanceUpdateLimiterImpl;
import com.jozufozu.flywheel.impl.visualization.ratelimit.NonLimiter; import com.jozufozu.flywheel.impl.visualization.ratelimit.NonLimiter;

View file

@ -38,9 +38,9 @@ public class VisualUpdatePlan<C> implements SimplyComposedPlan<C> {
@NotNull @NotNull
private Plan<C> updatePlans() { private Plan<C> updatePlans() {
if (plan == null) { if (plan == null) {
plan = new NestedPlan<>(initializer.get()).maybeSimplify(); plan = new NestedPlan<>(initializer.get()).simplify();
} else if (needsSimplify) { } else if (needsSimplify) {
plan = plan.maybeSimplify(); plan = plan.simplify();
} }
needsSimplify = false; needsSimplify = false;

View file

@ -48,7 +48,7 @@ public class OrientedType implements InstanceType<OrientedInstance> {
@Override @Override
public InstanceVertexTransformer<OrientedInstance> getVertexTransformer() { public InstanceVertexTransformer<OrientedInstance> getVertexTransformer() {
return (vertexList, instance, level) -> { return (vertexList, instance) -> {
Quaternion q = new Quaternion(instance.qX, instance.qY, instance.qZ, instance.qW); Quaternion q = new Quaternion(instance.qX, instance.qY, instance.qZ, instance.qW);
Matrix4f modelMatrix = new Matrix4f(); Matrix4f modelMatrix = new Matrix4f();

View file

@ -43,7 +43,7 @@ public class TransformedType implements InstanceType<TransformedInstance> {
@Override @Override
public InstanceVertexTransformer<TransformedInstance> getVertexTransformer() { public InstanceVertexTransformer<TransformedInstance> getVertexTransformer() {
return (vertexList, instance, level) -> { return (vertexList, instance) -> {
float r = RenderMath.uf(instance.r); float r = RenderMath.uf(instance.r);
float g = RenderMath.uf(instance.g); float g = RenderMath.uf(instance.g);
float b = RenderMath.uf(instance.b); float b = RenderMath.uf(instance.b);

View file

@ -14,9 +14,9 @@ public record BarrierPlan<C>(Plan<C> first, Plan<C> second) implements SimplyCom
} }
@Override @Override
public Plan<C> maybeSimplify() { public Plan<C> simplify() {
var first = this.first.maybeSimplify(); var first = this.first.simplify();
var second = this.second.maybeSimplify(); var second = this.second.simplify();
if (first == UnitPlan.of()) { if (first == UnitPlan.of()) {
return second; return second;

View file

@ -13,8 +13,8 @@ public record MapContextPlan<C, D>(Function<C, D> map, Plan<D> plan) implements
} }
@Override @Override
public Plan<C> maybeSimplify() { public Plan<C> simplify() {
var maybeSimplified = plan.maybeSimplify(); var maybeSimplified = plan.simplify();
if (maybeSimplified instanceof UnitPlan) { if (maybeSimplified instanceof UnitPlan) {
return UnitPlan.of(); return UnitPlan.of();

View file

@ -44,14 +44,14 @@ public record NestedPlan<C>(List<Plan<C>> parallelPlans) implements SimplyCompos
} }
@Override @Override
public Plan<C> maybeSimplify() { public Plan<C> simplify() {
if (parallelPlans.isEmpty()) { if (parallelPlans.isEmpty()) {
return UnitPlan.of(); return UnitPlan.of();
} }
if (parallelPlans.size() == 1) { if (parallelPlans.size() == 1) {
return parallelPlans.get(0) return parallelPlans.get(0)
.maybeSimplify(); .simplify();
} }
var simplifiedTasks = new ArrayList<ContextConsumer<C>>(); var simplifiedTasks = new ArrayList<ContextConsumer<C>>();
@ -59,7 +59,7 @@ public record NestedPlan<C>(List<Plan<C>> parallelPlans) implements SimplyCompos
var toVisit = new ArrayDeque<>(parallelPlans); var toVisit = new ArrayDeque<>(parallelPlans);
while (!toVisit.isEmpty()) { while (!toVisit.isEmpty()) {
var plan = toVisit.pop() var plan = toVisit.pop()
.maybeSimplify(); .simplify();
if (plan == UnitPlan.of()) { if (plan == UnitPlan.of()) {
continue; continue;

View file

@ -45,7 +45,7 @@ public record SimplePlan<C>(List<ContextConsumer<C>> parallelTasks) implements S
} }
@Override @Override
public Plan<C> maybeSimplify() { public Plan<C> simplify() {
if (parallelTasks.isEmpty()) { if (parallelTasks.isEmpty()) {
return UnitPlan.of(); return UnitPlan.of();
} }

View file

@ -26,7 +26,7 @@ public interface SimplyComposedPlan<C> extends Plan<C> {
} }
@Override @Override
default Plan<C> maybeSimplify() { default Plan<C> simplify() {
return this; return this;
} }
} }

View file

@ -42,7 +42,7 @@ public class UnitPlan<C> implements Plan<C> {
} }
@Override @Override
public Plan<C> maybeSimplify() { public Plan<C> simplify() {
return this; return this;
} }
} }

View file

@ -15,36 +15,36 @@ public class PlanSimplificationTest {
@Test @Test
void emptyPlans() { void emptyPlans() {
var empty = NestedPlan.of(); var empty = NestedPlan.of();
Assertions.assertEquals(empty.maybeSimplify(), UnitPlan.of()); Assertions.assertEquals(empty.simplify(), UnitPlan.of());
var simpleEmpty = SimplePlan.of(); var simpleEmpty = SimplePlan.of();
Assertions.assertEquals(simpleEmpty.maybeSimplify(), UnitPlan.of()); Assertions.assertEquals(simpleEmpty.simplify(), UnitPlan.of());
} }
@Test @Test
void nestedSimplePlans() { void nestedSimplePlans() {
var twoSimple = NestedPlan.of(SimplePlan.of(NOOP, NOOP, NOOP), SIMPLE); var twoSimple = NestedPlan.of(SimplePlan.of(NOOP, NOOP, NOOP), SIMPLE);
Assertions.assertEquals(twoSimple.maybeSimplify(), SimplePlan.of(NOOP, NOOP, NOOP, NOOP)); Assertions.assertEquals(twoSimple.simplify(), SimplePlan.of(NOOP, NOOP, NOOP, NOOP));
var threeSimple = NestedPlan.of(SIMPLE, SIMPLE, SIMPLE); var threeSimple = NestedPlan.of(SIMPLE, SIMPLE, SIMPLE);
Assertions.assertEquals(threeSimple.maybeSimplify(), SimplePlan.of(NOOP, NOOP, NOOP)); Assertions.assertEquals(threeSimple.simplify(), SimplePlan.of(NOOP, NOOP, NOOP));
} }
@Test @Test
void oneNestedPlan() { void oneNestedPlan() {
var oneSimple = NestedPlan.of(SIMPLE); var oneSimple = NestedPlan.of(SIMPLE);
Assertions.assertEquals(oneSimple.maybeSimplify(), SIMPLE); Assertions.assertEquals(oneSimple.simplify(), SIMPLE);
var mainThreadNoop = new OnMainThreadPlan<>(NOOP); var mainThreadNoop = new OnMainThreadPlan<>(NOOP);
var oneMainThread = NestedPlan.of(mainThreadNoop); var oneMainThread = NestedPlan.of(mainThreadNoop);
Assertions.assertEquals(oneMainThread.maybeSimplify(), mainThreadNoop); Assertions.assertEquals(oneMainThread.simplify(), mainThreadNoop);
var barrier = new BarrierPlan<>(SIMPLE, SIMPLE); var barrier = new BarrierPlan<>(SIMPLE, SIMPLE);
var oneBarrier = NestedPlan.of(barrier); var oneBarrier = NestedPlan.of(barrier);
Assertions.assertEquals(oneBarrier.maybeSimplify(), barrier); Assertions.assertEquals(oneBarrier.simplify(), barrier);
} }
@Test @Test
@ -52,16 +52,16 @@ public class PlanSimplificationTest {
var outer = NestedPlan.of(SIMPLE); var outer = NestedPlan.of(SIMPLE);
var outermost = NestedPlan.of(outer); var outermost = NestedPlan.of(outer);
Assertions.assertEquals(outermost.maybeSimplify(), SIMPLE); Assertions.assertEquals(outermost.simplify(), SIMPLE);
} }
@Test @Test
void nestedUnitPlan() { void nestedUnitPlan() {
var onlyUnit = NestedPlan.of(UnitPlan.of(), UnitPlan.of(), UnitPlan.of()); var onlyUnit = NestedPlan.of(UnitPlan.of(), UnitPlan.of(), UnitPlan.of());
Assertions.assertEquals(onlyUnit.maybeSimplify(), UnitPlan.of()); Assertions.assertEquals(onlyUnit.simplify(), UnitPlan.of());
var unitAndSimple = NestedPlan.of(UnitPlan.of(), UnitPlan.of(), SIMPLE); var unitAndSimple = NestedPlan.of(UnitPlan.of(), UnitPlan.of(), SIMPLE);
Assertions.assertEquals(unitAndSimple.maybeSimplify(), SIMPLE); Assertions.assertEquals(unitAndSimple.simplify(), SIMPLE);
} }
@Test @Test
@ -70,11 +70,11 @@ public class PlanSimplificationTest {
}); });
var nested = NestedPlan.of(mainThreadNoop, SIMPLE); var nested = NestedPlan.of(mainThreadNoop, SIMPLE);
Assertions.assertEquals(nested.maybeSimplify(), nested); // cannot simplify Assertions.assertEquals(nested.simplify(), nested); // cannot simplify
var barrier = new BarrierPlan<>(SIMPLE, SIMPLE); var barrier = new BarrierPlan<>(SIMPLE, SIMPLE);
var complex = NestedPlan.of(barrier, nested); var complex = NestedPlan.of(barrier, nested);
Assertions.assertEquals(complex.maybeSimplify(), NestedPlan.of(barrier, mainThreadNoop, SIMPLE)); Assertions.assertEquals(complex.simplify(), NestedPlan.of(barrier, mainThreadNoop, SIMPLE));
} }
@Test @Test
@ -84,7 +84,7 @@ public class PlanSimplificationTest {
var barrier = new BarrierPlan<>(SIMPLE, SIMPLE); var barrier = new BarrierPlan<>(SIMPLE, SIMPLE);
var oneMainThread = NestedPlan.of(mainThreadNoop, NestedPlan.of(mainThreadNoop, barrier, barrier)); var oneMainThread = NestedPlan.of(mainThreadNoop, NestedPlan.of(mainThreadNoop, barrier, barrier));
Assertions.assertEquals(oneMainThread.maybeSimplify(), NestedPlan.of(mainThreadNoop, mainThreadNoop, barrier, barrier)); Assertions.assertEquals(oneMainThread.simplify(), NestedPlan.of(mainThreadNoop, mainThreadNoop, barrier, barrier));
} }
@Test @Test
@ -92,21 +92,21 @@ public class PlanSimplificationTest {
var barrier = new BarrierPlan<>(SIMPLE, SIMPLE); var barrier = new BarrierPlan<>(SIMPLE, SIMPLE);
var oneMainThread = NestedPlan.of(barrier, NestedPlan.of(UnitPlan.of(), UnitPlan.of())); var oneMainThread = NestedPlan.of(barrier, NestedPlan.of(UnitPlan.of(), UnitPlan.of()));
Assertions.assertEquals(oneMainThread.maybeSimplify(), barrier); Assertions.assertEquals(oneMainThread.simplify(), barrier);
} }
@Test @Test
void barrierPlan() { void barrierPlan() {
var doubleUnit = new BarrierPlan<>(UnitPlan.of(), UnitPlan.of()); var doubleUnit = new BarrierPlan<>(UnitPlan.of(), UnitPlan.of());
Assertions.assertEquals(doubleUnit.maybeSimplify(), UnitPlan.of()); Assertions.assertEquals(doubleUnit.simplify(), UnitPlan.of());
var simpleThenUnit = new BarrierPlan<>(SIMPLE, UnitPlan.of()); var simpleThenUnit = new BarrierPlan<>(SIMPLE, UnitPlan.of());
Assertions.assertEquals(simpleThenUnit.maybeSimplify(), SIMPLE); Assertions.assertEquals(simpleThenUnit.simplify(), SIMPLE);
var unitThenSimple = new BarrierPlan<>(UnitPlan.of(), SIMPLE); var unitThenSimple = new BarrierPlan<>(UnitPlan.of(), SIMPLE);
Assertions.assertEquals(unitThenSimple.maybeSimplify(), SIMPLE); Assertions.assertEquals(unitThenSimple.simplify(), SIMPLE);
var simpleThenSimple = new BarrierPlan<>(SIMPLE, SIMPLE); var simpleThenSimple = new BarrierPlan<>(SIMPLE, SIMPLE);
Assertions.assertEquals(simpleThenSimple.maybeSimplify(), new BarrierPlan<>(SIMPLE, SIMPLE)); Assertions.assertEquals(simpleThenSimple.simplify(), new BarrierPlan<>(SIMPLE, SIMPLE));
} }
} }