From ed35c5a429f35342fccee2f09bf5fdf9bcaca194 Mon Sep 17 00:00:00 2001 From: Jozufozu Date: Sat, 14 Sep 2024 16:50:02 -0700 Subject: [PATCH] Reduce and reuse - Create subclass to recycle PoseStack.Pose objects - Add mixin/liblink to access a PoseStack's inner deque --- .../flywheel/lib/internal/FlwLibLink.java | 3 ++ .../flywheel/lib/util/RecyclingPoseStack.java | 42 +++++++++++++++++++ .../flywheel/impl/FlwLibLinkImpl.java | 7 ++++ .../impl/mixin/PoseStackAccessor.java | 14 +++++++ .../flywheel/vanilla/ChestVisual.java | 3 +- .../flywheel/vanilla/MinecartVisual.java | 3 +- .../flywheel/vanilla/ShulkerBoxVisual.java | 3 +- .../main/resources/flywheel.impl.mixins.json | 1 + 8 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 common/src/lib/java/dev/engine_room/flywheel/lib/util/RecyclingPoseStack.java create mode 100644 common/src/main/java/dev/engine_room/flywheel/impl/mixin/PoseStackAccessor.java diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/internal/FlwLibLink.java b/common/src/lib/java/dev/engine_room/flywheel/lib/internal/FlwLibLink.java index fc0ae8dfe..9a112c07d 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/internal/FlwLibLink.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/internal/FlwLibLink.java @@ -1,5 +1,6 @@ package dev.engine_room.flywheel.lib.internal; +import java.util.Deque; import java.util.Map; import org.slf4j.Logger; @@ -21,4 +22,6 @@ public interface FlwLibLink { Map getModelPartChildren(ModelPart part); void compileModelPart(ModelPart part, PoseStack.Pose pose, VertexConsumer consumer, int light, int overlay, float red, float green, float blue, float alpha); + + Deque getPoseStack(PoseStack stack); } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/util/RecyclingPoseStack.java b/common/src/lib/java/dev/engine_room/flywheel/lib/util/RecyclingPoseStack.java new file mode 100644 index 000000000..0c0fefebe --- /dev/null +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/util/RecyclingPoseStack.java @@ -0,0 +1,42 @@ +package dev.engine_room.flywheel.lib.util; + +import java.util.ArrayDeque; +import java.util.Deque; + +import com.mojang.blaze3d.vertex.PoseStack; + +import dev.engine_room.flywheel.lib.internal.FlwLibLink; + +/** + * A {@link PoseStack} that recycles {@link PoseStack.Pose} objects. + * + *

Vanilla's {@link PoseStack} can get quite expensive to use when each game object needs to + * maintain their own stack. This class helps alleviate memory pressure by making Pose objects + * long-lived. Note that this means that you CANNOT safely store a Pose object outside + * the RecyclingPoseStack that created it. + */ +public class RecyclingPoseStack extends PoseStack { + private final Deque recycleBin = new ArrayDeque<>(); + + @Override + public void pushPose() { + if (recycleBin.isEmpty()) { + super.pushPose(); + } else { + var last = last(); + var recycle = recycleBin.pop(); + recycle.pose() + .set(last.pose()); + recycle.normal() + .set(last.normal()); + FlwLibLink.INSTANCE.getPoseStack(this) + .addLast(recycle); + } + } + + @Override + public void popPose() { + recycleBin.push(FlwLibLink.INSTANCE.getPoseStack(this) + .removeLast()); + } +} diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/FlwLibLinkImpl.java b/common/src/main/java/dev/engine_room/flywheel/impl/FlwLibLinkImpl.java index 003037264..47fffeeb6 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/FlwLibLinkImpl.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/FlwLibLinkImpl.java @@ -1,5 +1,6 @@ package dev.engine_room.flywheel.impl; +import java.util.Deque; import java.util.Map; import org.slf4j.Logger; @@ -9,6 +10,7 @@ import dev.engine_room.flywheel.impl.extension.PoseStackExtension; import dev.engine_room.flywheel.impl.mixin.ModelPartAccessor; +import dev.engine_room.flywheel.impl.mixin.PoseStackAccessor; import dev.engine_room.flywheel.lib.internal.FlwLibLink; import dev.engine_room.flywheel.lib.transform.PoseTransformStack; import net.minecraft.client.model.geom.ModelPart; @@ -33,4 +35,9 @@ public Map getModelPartChildren(ModelPart part) { public void compileModelPart(ModelPart part, PoseStack.Pose pose, VertexConsumer consumer, int light, int overlay, float red, float green, float blue, float alpha) { ((ModelPartAccessor) (Object) part).flywheel$compile(pose, consumer, light, overlay, red, green, blue, alpha); } + + @Override + public Deque getPoseStack(PoseStack stack) { + return ((PoseStackAccessor) stack).flywheel$getPoseStack(); + } } diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/mixin/PoseStackAccessor.java b/common/src/main/java/dev/engine_room/flywheel/impl/mixin/PoseStackAccessor.java new file mode 100644 index 000000000..22478d2a3 --- /dev/null +++ b/common/src/main/java/dev/engine_room/flywheel/impl/mixin/PoseStackAccessor.java @@ -0,0 +1,14 @@ +package dev.engine_room.flywheel.impl.mixin; + +import java.util.Deque; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import com.mojang.blaze3d.vertex.PoseStack; + +@Mixin(PoseStack.class) +public interface PoseStackAccessor { + @Accessor("poseStack") + Deque flywheel$getPoseStack(); +} diff --git a/common/src/main/java/dev/engine_room/flywheel/vanilla/ChestVisual.java b/common/src/main/java/dev/engine_room/flywheel/vanilla/ChestVisual.java index 16c3849b2..9025f5d0a 100644 --- a/common/src/main/java/dev/engine_room/flywheel/vanilla/ChestVisual.java +++ b/common/src/main/java/dev/engine_room/flywheel/vanilla/ChestVisual.java @@ -18,6 +18,7 @@ import dev.engine_room.flywheel.lib.model.RetexturedMesh; import dev.engine_room.flywheel.lib.model.part.InstanceTree; import dev.engine_room.flywheel.lib.transform.TransformStack; +import dev.engine_room.flywheel.lib.util.RecyclingPoseStack; import dev.engine_room.flywheel.lib.visual.AbstractBlockEntityVisual; import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual; import it.unimi.dsi.fastutil.floats.Float2FloatFunction; @@ -59,7 +60,7 @@ public class ChestVisual extends Abstrac @Nullable private final InstanceTree lock; - private final PoseStack poseStack = new PoseStack(); + private final PoseStack poseStack = new RecyclingPoseStack(); private final BrightnessCombiner brightnessCombiner = new BrightnessCombiner(); @Nullable private final DoubleBlockCombiner.NeighborCombineResult neighborCombineResult; diff --git a/common/src/main/java/dev/engine_room/flywheel/vanilla/MinecartVisual.java b/common/src/main/java/dev/engine_room/flywheel/vanilla/MinecartVisual.java index bc58879d8..0ba3efc60 100644 --- a/common/src/main/java/dev/engine_room/flywheel/vanilla/MinecartVisual.java +++ b/common/src/main/java/dev/engine_room/flywheel/vanilla/MinecartVisual.java @@ -16,6 +16,7 @@ import dev.engine_room.flywheel.lib.model.Models; import dev.engine_room.flywheel.lib.model.SingleMeshModel; import dev.engine_room.flywheel.lib.model.part.ModelPartConverter; +import dev.engine_room.flywheel.lib.util.RecyclingPoseStack; import dev.engine_room.flywheel.lib.visual.ComponentEntityVisual; import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual; import dev.engine_room.flywheel.lib.visual.SimpleTickableVisual; @@ -52,7 +53,7 @@ public class MinecartVisual extends ComponentEntityV private final ModelHolder bodyModel; - private final PoseStack stack = new PoseStack(); + private final PoseStack stack = new RecyclingPoseStack(); private BlockState blockState; private boolean active; diff --git a/common/src/main/java/dev/engine_room/flywheel/vanilla/ShulkerBoxVisual.java b/common/src/main/java/dev/engine_room/flywheel/vanilla/ShulkerBoxVisual.java index 9e9e17925..084c5fb03 100644 --- a/common/src/main/java/dev/engine_room/flywheel/vanilla/ShulkerBoxVisual.java +++ b/common/src/main/java/dev/engine_room/flywheel/vanilla/ShulkerBoxVisual.java @@ -17,6 +17,7 @@ import dev.engine_room.flywheel.lib.model.SingleMeshModel; import dev.engine_room.flywheel.lib.model.part.ModelPartConverter; import dev.engine_room.flywheel.lib.transform.TransformStack; +import dev.engine_room.flywheel.lib.util.RecyclingPoseStack; import dev.engine_room.flywheel.lib.visual.AbstractBlockEntityVisual; import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual; import net.minecraft.client.model.geom.ModelLayers; @@ -45,7 +46,7 @@ public class ShulkerBoxVisual extends AbstractBlockEntityVisual