From 246543c76bf8235eb41a2edd0518b166d8adbbbb Mon Sep 17 00:00:00 2001 From: PepperCode1 <44146161+PepperCode1@users.noreply.github.com> Date: Mon, 3 Jul 2023 13:53:51 -0700 Subject: [PATCH] Fix memory leaks - Fix CopycatPanelModel using wrong state during trapdoor special case - Update Flywheel --- build.gradle | 1 + gradle.properties | 2 +- .../render/ContraptionRenderDispatcher.java | 8 ++-- .../contraptions/render/FlwContraption.java | 7 ++-- .../decoration/copycat/CopycatPanelModel.java | 2 +- .../waterwheel/WaterWheelInstance.java | 2 +- .../schematics/client/SchematicRenderer.java | 21 ++++++---- .../ponder/element/WorldSectionElement.java | 25 +++++------ .../render/BakedModelRenderHelper.java | 8 ++-- .../foundation/render/SuperByteBuffer.java | 41 +++++++++++-------- .../render/SuperByteBufferCache.java | 2 + 11 files changed, 70 insertions(+), 49 deletions(-) diff --git a/build.gradle b/build.gradle index 5671c4535..16a1ebd65 100644 --- a/build.gradle +++ b/build.gradle @@ -159,6 +159,7 @@ repositories { } } + mavenLocal() flatDir { dirs 'libs' } diff --git a/gradle.properties b/gradle.properties index 4fbade479..63d62e52f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -23,7 +23,7 @@ use_parchment = true # dependency versions registrate_version = MC1.18.2-1.1.3 flywheel_minecraft_version = 1.18.2 -flywheel_version = 0.6.9-100 +flywheel_version = 0.6.9-101 jei_minecraft_version = 1.18.2 jei_version = 9.7.0.209 curios_minecraft_version = 1.18.2 diff --git a/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionRenderDispatcher.java b/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionRenderDispatcher.java index 5f9015d03..baa0b5ca4 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionRenderDispatcher.java +++ b/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionRenderDispatcher.java @@ -7,6 +7,7 @@ import org.apache.commons.lang3.tuple.Pair; import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.gl.error.GlError; import com.jozufozu.flywheel.config.BackendType; +import com.jozufozu.flywheel.core.model.ShadeSeparatedBufferedData; import com.jozufozu.flywheel.core.model.WorldModelBuilder; import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; import com.jozufozu.flywheel.event.BeginFrameEvent; @@ -15,7 +16,6 @@ import com.jozufozu.flywheel.event.ReloadRenderersEvent; import com.jozufozu.flywheel.event.RenderLayerEvent; import com.jozufozu.flywheel.util.WorldAttached; import com.jozufozu.flywheel.util.transform.TransformStack; -import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllMovementBehaviours; import com.simibubi.create.content.contraptions.AbstractContraptionEntity; @@ -171,11 +171,13 @@ public class ContraptionRenderDispatcher { public static SuperByteBuffer buildStructureBuffer(VirtualRenderWorld renderWorld, Contraption c, RenderType layer) { Collection values = c.getRenderedBlocks(); - BufferBuilder builder = new WorldModelBuilder(layer).withRenderWorld(renderWorld) + ShadeSeparatedBufferedData data = new WorldModelBuilder(layer).withRenderWorld(renderWorld) .withBlocks(values) .withModelData(c.modelData) .build(); - return new SuperByteBuffer(builder); + SuperByteBuffer sbb = new SuperByteBuffer(data); + data.release(); + return sbb; } public static int getLight(Level world, float lx, float ly, float lz) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/render/FlwContraption.java b/src/main/java/com/simibubi/create/content/contraptions/render/FlwContraption.java index a79f7fbc5..bb44e21a8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/render/FlwContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/render/FlwContraption.java @@ -132,8 +132,9 @@ public class FlwContraption extends ContraptionRenderInfo { } private void buildLayers() { - for (ArrayModelRenderer buffer : renderLayers.values()) { - buffer.delete(); + for (ArrayModelRenderer renderer : renderLayers.values()) { + renderer.delete(); + renderer.getModel().delete(); } renderLayers.clear(); @@ -145,7 +146,7 @@ public class FlwContraption extends ContraptionRenderInfo { Model layerModel = new WorldModelBuilder(layer).withRenderWorld(renderWorld) .withModelData(contraption.modelData) .withBlocks(renderedBlocks) - .intoMesh(layer + "_" + contraption.entity.getId()); + .toModel(layer + "_" + contraption.entity.getId()); renderLayers.put(layer, new ArrayModelRenderer(layerModel)); } } diff --git a/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatPanelModel.java b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatPanelModel.java index af64f4ac0..a01148a2b 100644 --- a/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatPanelModel.java +++ b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatPanelModel.java @@ -42,7 +42,7 @@ public class CopycatPanelModel extends CopycatModel { specialCopycatModelState = AllBlocks.COPYCAT_BARS.getDefaultState(); if (CopycatSpecialCases.isTrapdoorMaterial(material)) return blockRenderer.getBlockModel(material) - .getQuads(state, side, rand, wrappedData); + .getQuads(material, side, rand, wrappedData); if (specialCopycatModelState != null) { BakedModel blockModel = blockRenderer diff --git a/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelInstance.java b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelInstance.java index b00ca8464..16ae300bf 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelInstance.java +++ b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelInstance.java @@ -49,7 +49,7 @@ public class WaterWheelInstance extends CutoutR dir = state.getValue(WaterWheelBlock.FACING); } PoseStack transform = CachedBufferer.rotateToFaceVertical(dir).get(); - return new BlockModel(model, Blocks.AIR.defaultBlockState(), transform); + return BlockModel.of(model, Blocks.AIR.defaultBlockState(), transform); }); } } diff --git a/src/main/java/com/simibubi/create/content/schematics/client/SchematicRenderer.java b/src/main/java/com/simibubi/create/content/schematics/client/SchematicRenderer.java index 26f5a368f..98d7faabc 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/SchematicRenderer.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/SchematicRenderer.java @@ -5,7 +5,7 @@ import java.util.Map; import java.util.Random; import com.jozufozu.flywheel.core.model.ModelUtil; -import com.jozufozu.flywheel.core.model.ShadeSeparatedBufferBuilder; +import com.jozufozu.flywheel.core.model.ShadeSeparatedBufferedData; import com.jozufozu.flywheel.core.model.ShadeSeparatingVertexConsumer; import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.DefaultVertexFormat; @@ -79,11 +79,15 @@ public class SchematicRenderer { } protected void redraw() { + bufferCache.forEach((layer, sbb) -> sbb.delete()); bufferCache.clear(); + for (RenderType layer : RenderType.chunkBufferLayers()) { SuperByteBuffer buffer = drawLayer(layer); if (!buffer.isEmpty()) bufferCache.put(layer, buffer); + else + buffer.delete(); } } @@ -99,12 +103,12 @@ public class SchematicRenderer { BoundingBox bounds = renderWorld.getBounds(); ShadeSeparatingVertexConsumer shadeSeparatingWrapper = objects.shadeSeparatingWrapper; - ShadeSeparatedBufferBuilder builder = new ShadeSeparatedBufferBuilder(512); + BufferBuilder shadedBuilder = objects.shadedBuilder; BufferBuilder unshadedBuilder = objects.unshadedBuilder; - builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK); + shadedBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK); unshadedBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK); - shadeSeparatingWrapper.prepare(builder, unshadedBuilder); + shadeSeparatingWrapper.prepare(shadedBuilder, unshadedBuilder); ForgeHooksClient.setRenderType(layer); ModelBlockRenderer.enableCaching(); @@ -127,13 +131,13 @@ public class SchematicRenderer { ForgeHooksClient.setRenderType(null); shadeSeparatingWrapper.clear(); - unshadedBuilder.end(); - builder.appendUnshadedVertices(unshadedBuilder); - builder.end(); + ShadeSeparatedBufferedData bufferedData = ModelUtil.endAndCombine(shadedBuilder, unshadedBuilder); renderWorld.renderMode = false; - return new SuperByteBuffer(builder); + SuperByteBuffer sbb = new SuperByteBuffer(bufferedData); + bufferedData.release(); + return sbb; } private static int getLayerCount() { @@ -146,6 +150,7 @@ public class SchematicRenderer { public final Random random = new Random(); public final BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); public final ShadeSeparatingVertexConsumer shadeSeparatingWrapper = new ShadeSeparatingVertexConsumer(); + public final BufferBuilder shadedBuilder = new BufferBuilder(512); public final BufferBuilder unshadedBuilder = new BufferBuilder(512); } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/element/WorldSectionElement.java b/src/main/java/com/simibubi/create/foundation/ponder/element/WorldSectionElement.java index 64b7ca9ce..96d3d58a6 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/element/WorldSectionElement.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/element/WorldSectionElement.java @@ -8,7 +8,7 @@ import java.util.Random; import java.util.function.Consumer; import com.jozufozu.flywheel.core.model.ModelUtil; -import com.jozufozu.flywheel.core.model.ShadeSeparatedBufferBuilder; +import com.jozufozu.flywheel.core.model.ShadeSeparatedBufferedData; import com.jozufozu.flywheel.core.model.ShadeSeparatingVertexConsumer; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.BufferBuilder; @@ -258,7 +258,7 @@ public class WorldSectionElement extends AnimatedSceneElement { prevAnimatedRotation = animatedRotation; if (!isVisible()) return; - loadTEsIfMissing(scene.getWorld()); + loadBEsIfMissing(scene.getWorld()); renderedBlockEntities.removeIf(be -> scene.getWorld() .getBlockEntity(be.getBlockPos()) != be); tickableBlockEntities.removeIf(be -> scene.getWorld() @@ -277,7 +277,7 @@ public class WorldSectionElement extends AnimatedSceneElement { redraw = false; } - protected void loadTEsIfMissing(PonderWorld world) { + protected void loadBEsIfMissing(PonderWorld world) { if (renderedBlockEntities != null) return; tickableBlockEntities = new ArrayList<>(); @@ -405,7 +405,7 @@ public class WorldSectionElement extends AnimatedSceneElement { } private void renderBlockEntities(PonderWorld world, PoseStack ms, MultiBufferSource buffer, float pt) { - loadTEsIfMissing(world); + loadBEsIfMissing(world); BlockEntityRenderHelper.renderBlockEntities(world, renderedBlockEntities, ms, buffer, pt); } @@ -416,12 +416,12 @@ public class WorldSectionElement extends AnimatedSceneElement { PoseStack poseStack = objects.poseStack; Random random = objects.random; ShadeSeparatingVertexConsumer shadeSeparatingWrapper = objects.shadeSeparatingWrapper; - ShadeSeparatedBufferBuilder builder = new ShadeSeparatedBufferBuilder(512); + BufferBuilder shadedBuilder = objects.shadedBuilder; BufferBuilder unshadedBuilder = objects.unshadedBuilder; - builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK); + shadedBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK); unshadedBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK); - shadeSeparatingWrapper.prepare(builder, unshadedBuilder); + shadeSeparatingWrapper.prepare(shadedBuilder, unshadedBuilder); world.setMask(this.section); ForgeHooksClient.setRenderType(layer); @@ -440,7 +440,7 @@ public class WorldSectionElement extends AnimatedSceneElement { } if (!fluidState.isEmpty() && ItemBlockRenderTypes.canRenderInLayer(fluidState, layer)) - dispatcher.renderLiquid(pos, world, builder, state, fluidState); + dispatcher.renderLiquid(pos, world, shadedBuilder, state, fluidState); poseStack.popPose(); }); @@ -449,17 +449,18 @@ public class WorldSectionElement extends AnimatedSceneElement { world.clearMask(); shadeSeparatingWrapper.clear(); - unshadedBuilder.end(); - builder.appendUnshadedVertices(unshadedBuilder); - builder.end(); + ShadeSeparatedBufferedData bufferedData = ModelUtil.endAndCombine(shadedBuilder, unshadedBuilder); - return new SuperByteBuffer(builder); + SuperByteBuffer sbb = new SuperByteBuffer(bufferedData); + bufferedData.release(); + return sbb; } private static class ThreadLocalObjects { public final PoseStack poseStack = new PoseStack(); public final Random random = new Random(); public final ShadeSeparatingVertexConsumer shadeSeparatingWrapper = new ShadeSeparatingVertexConsumer(); + public final BufferBuilder shadedBuilder = new BufferBuilder(512); public final BufferBuilder unshadedBuilder = new BufferBuilder(512); } diff --git a/src/main/java/com/simibubi/create/foundation/render/BakedModelRenderHelper.java b/src/main/java/com/simibubi/create/foundation/render/BakedModelRenderHelper.java index aa8300cde..de4cb67bc 100644 --- a/src/main/java/com/simibubi/create/foundation/render/BakedModelRenderHelper.java +++ b/src/main/java/com/simibubi/create/foundation/render/BakedModelRenderHelper.java @@ -1,7 +1,7 @@ package com.simibubi.create.foundation.render; import com.jozufozu.flywheel.core.model.ModelUtil; -import com.mojang.blaze3d.vertex.BufferBuilder; +import com.jozufozu.flywheel.core.model.ShadeSeparatedBufferedData; import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.Minecraft; @@ -22,8 +22,10 @@ public class BakedModelRenderHelper { } public static SuperByteBuffer standardModelRender(BakedModel model, BlockState referenceState, PoseStack ms) { - BufferBuilder builder = ModelUtil.getBufferBuilder(model, referenceState, ms); - return new SuperByteBuffer(builder); + ShadeSeparatedBufferedData data = ModelUtil.getBufferedData(model, referenceState, ms); + SuperByteBuffer sbb = new SuperByteBuffer(data); + data.release(); + return sbb; } } diff --git a/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java b/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java index bfd39989e..409489e3d 100644 --- a/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java +++ b/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java @@ -6,16 +6,14 @@ import java.util.function.IntPredicate; import com.jozufozu.flywheel.api.vertex.ShadedVertexList; import com.jozufozu.flywheel.api.vertex.VertexList; import com.jozufozu.flywheel.backend.ShadersModHandler; -import com.jozufozu.flywheel.core.model.ShadeSeparatedBufferBuilder; +import com.jozufozu.flywheel.core.model.ShadeSeparatedBufferedData; import com.jozufozu.flywheel.core.vertex.BlockVertexList; import com.jozufozu.flywheel.util.DiffuseLightCalculator; import com.jozufozu.flywheel.util.transform.TStack; import com.jozufozu.flywheel.util.transform.Transform; import com.mojang.blaze3d.vertex.BufferBuilder; -import com.mojang.blaze3d.vertex.BufferBuilder.DrawState; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; -import com.mojang.datafixers.util.Pair; import com.mojang.math.Matrix3f; import com.mojang.math.Matrix4f; import com.mojang.math.Quaternion; @@ -41,7 +39,7 @@ public class SuperByteBuffer implements Transform, TStack, TStack pair = buf.popNextBuffer(); - DrawState drawState = pair.getFirst(); - ByteBuffer buffer = pair.getSecond(); + public SuperByteBuffer(ByteBuffer vertexBuffer, BufferBuilder.DrawState drawState, int unshadedStartVertex) { int vertexCount = drawState.vertexCount(); int stride = drawState.format().getVertexSize(); - if (buf instanceof ShadeSeparatedBufferBuilder separated) { - ShadedVertexList template = new BlockVertexList.Shaded(buffer, vertexCount, stride, separated.getUnshadedStartVertex()); - shadedPredicate = template::isShaded; - this.template = template; - } else { - template = new BlockVertexList(buffer, vertexCount, stride); - shadedPredicate = index -> true; - } + ShadedVertexList template = new BlockVertexList.Shaded(vertexBuffer, vertexCount, stride, unshadedStartVertex); + shadedPredicate = template::isShaded; + this.template = template; + + transforms.pushPose(); + } + + public SuperByteBuffer(ShadeSeparatedBufferedData data) { + this(data.vertexBuffer(), data.drawState(), data.unshadedStartVertex()); + } + + public SuperByteBuffer(ByteBuffer vertexBuffer, BufferBuilder.DrawState drawState) { + int vertexCount = drawState.vertexCount(); + int stride = drawState.format().getVertexSize(); + + template = new BlockVertexList(vertexBuffer, vertexCount, stride); + shadedPredicate = index -> true; - transforms = new PoseStack(); transforms.pushPose(); } @@ -246,6 +249,10 @@ public class SuperByteBuffer implements Transform, TStack compartment) { caches.put(compartment, CacheBuilder.newBuilder() + .removalListener(n -> n.getValue().delete()) .build()); } public synchronized void registerCompartment(Compartment compartment, long ticksUntilExpired) { caches.put(compartment, CacheBuilder.newBuilder() .expireAfterAccess(ticksUntilExpired * 50, TimeUnit.MILLISECONDS) + .removalListener(n -> n.getValue().delete()) .build()); }