Fix memory leaks

- Fix CopycatPanelModel using wrong state during trapdoor special case
- Update Flywheel
This commit is contained in:
PepperCode1 2023-07-03 13:53:51 -07:00
parent 886398f679
commit 246543c76b
11 changed files with 70 additions and 49 deletions

View file

@ -159,6 +159,7 @@ repositories {
} }
} }
mavenLocal()
flatDir { flatDir {
dirs 'libs' dirs 'libs'
} }

View file

@ -23,7 +23,7 @@ use_parchment = true
# dependency versions # dependency versions
registrate_version = MC1.18.2-1.1.3 registrate_version = MC1.18.2-1.1.3
flywheel_minecraft_version = 1.18.2 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_minecraft_version = 1.18.2
jei_version = 9.7.0.209 jei_version = 9.7.0.209
curios_minecraft_version = 1.18.2 curios_minecraft_version = 1.18.2

View file

@ -7,6 +7,7 @@ import org.apache.commons.lang3.tuple.Pair;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.gl.error.GlError; import com.jozufozu.flywheel.backend.gl.error.GlError;
import com.jozufozu.flywheel.config.BackendType; 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.model.WorldModelBuilder;
import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld;
import com.jozufozu.flywheel.event.BeginFrameEvent; 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.event.RenderLayerEvent;
import com.jozufozu.flywheel.util.WorldAttached; import com.jozufozu.flywheel.util.WorldAttached;
import com.jozufozu.flywheel.util.transform.TransformStack; import com.jozufozu.flywheel.util.transform.TransformStack;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllMovementBehaviours; import com.simibubi.create.AllMovementBehaviours;
import com.simibubi.create.content.contraptions.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.AbstractContraptionEntity;
@ -171,11 +171,13 @@ public class ContraptionRenderDispatcher {
public static SuperByteBuffer buildStructureBuffer(VirtualRenderWorld renderWorld, Contraption c, public static SuperByteBuffer buildStructureBuffer(VirtualRenderWorld renderWorld, Contraption c,
RenderType layer) { RenderType layer) {
Collection<StructureTemplate.StructureBlockInfo> values = c.getRenderedBlocks(); Collection<StructureTemplate.StructureBlockInfo> values = c.getRenderedBlocks();
BufferBuilder builder = new WorldModelBuilder(layer).withRenderWorld(renderWorld) ShadeSeparatedBufferedData data = new WorldModelBuilder(layer).withRenderWorld(renderWorld)
.withBlocks(values) .withBlocks(values)
.withModelData(c.modelData) .withModelData(c.modelData)
.build(); .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) { public static int getLight(Level world, float lx, float ly, float lz) {

View file

@ -132,8 +132,9 @@ public class FlwContraption extends ContraptionRenderInfo {
} }
private void buildLayers() { private void buildLayers() {
for (ArrayModelRenderer buffer : renderLayers.values()) { for (ArrayModelRenderer renderer : renderLayers.values()) {
buffer.delete(); renderer.delete();
renderer.getModel().delete();
} }
renderLayers.clear(); renderLayers.clear();
@ -145,7 +146,7 @@ public class FlwContraption extends ContraptionRenderInfo {
Model layerModel = new WorldModelBuilder(layer).withRenderWorld(renderWorld) Model layerModel = new WorldModelBuilder(layer).withRenderWorld(renderWorld)
.withModelData(contraption.modelData) .withModelData(contraption.modelData)
.withBlocks(renderedBlocks) .withBlocks(renderedBlocks)
.intoMesh(layer + "_" + contraption.entity.getId()); .toModel(layer + "_" + contraption.entity.getId());
renderLayers.put(layer, new ArrayModelRenderer(layerModel)); renderLayers.put(layer, new ArrayModelRenderer(layerModel));
} }
} }

View file

@ -42,7 +42,7 @@ public class CopycatPanelModel extends CopycatModel {
specialCopycatModelState = AllBlocks.COPYCAT_BARS.getDefaultState(); specialCopycatModelState = AllBlocks.COPYCAT_BARS.getDefaultState();
if (CopycatSpecialCases.isTrapdoorMaterial(material)) if (CopycatSpecialCases.isTrapdoorMaterial(material))
return blockRenderer.getBlockModel(material) return blockRenderer.getBlockModel(material)
.getQuads(state, side, rand, wrappedData); .getQuads(material, side, rand, wrappedData);
if (specialCopycatModelState != null) { if (specialCopycatModelState != null) {
BakedModel blockModel = blockRenderer BakedModel blockModel = blockRenderer

View file

@ -49,7 +49,7 @@ public class WaterWheelInstance<T extends WaterWheelBlockEntity> extends CutoutR
dir = state.getValue(WaterWheelBlock.FACING); dir = state.getValue(WaterWheelBlock.FACING);
} }
PoseStack transform = CachedBufferer.rotateToFaceVertical(dir).get(); PoseStack transform = CachedBufferer.rotateToFaceVertical(dir).get();
return new BlockModel(model, Blocks.AIR.defaultBlockState(), transform); return BlockModel.of(model, Blocks.AIR.defaultBlockState(), transform);
}); });
} }
} }

View file

@ -5,7 +5,7 @@ import java.util.Map;
import java.util.Random; import java.util.Random;
import com.jozufozu.flywheel.core.model.ModelUtil; 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.core.model.ShadeSeparatingVertexConsumer;
import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.DefaultVertexFormat;
@ -79,11 +79,15 @@ public class SchematicRenderer {
} }
protected void redraw() { protected void redraw() {
bufferCache.forEach((layer, sbb) -> sbb.delete());
bufferCache.clear(); bufferCache.clear();
for (RenderType layer : RenderType.chunkBufferLayers()) { for (RenderType layer : RenderType.chunkBufferLayers()) {
SuperByteBuffer buffer = drawLayer(layer); SuperByteBuffer buffer = drawLayer(layer);
if (!buffer.isEmpty()) if (!buffer.isEmpty())
bufferCache.put(layer, buffer); bufferCache.put(layer, buffer);
else
buffer.delete();
} }
} }
@ -99,12 +103,12 @@ public class SchematicRenderer {
BoundingBox bounds = renderWorld.getBounds(); BoundingBox bounds = renderWorld.getBounds();
ShadeSeparatingVertexConsumer shadeSeparatingWrapper = objects.shadeSeparatingWrapper; ShadeSeparatingVertexConsumer shadeSeparatingWrapper = objects.shadeSeparatingWrapper;
ShadeSeparatedBufferBuilder builder = new ShadeSeparatedBufferBuilder(512); BufferBuilder shadedBuilder = objects.shadedBuilder;
BufferBuilder unshadedBuilder = objects.unshadedBuilder; 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); unshadedBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
shadeSeparatingWrapper.prepare(builder, unshadedBuilder); shadeSeparatingWrapper.prepare(shadedBuilder, unshadedBuilder);
ForgeHooksClient.setRenderType(layer); ForgeHooksClient.setRenderType(layer);
ModelBlockRenderer.enableCaching(); ModelBlockRenderer.enableCaching();
@ -127,13 +131,13 @@ public class SchematicRenderer {
ForgeHooksClient.setRenderType(null); ForgeHooksClient.setRenderType(null);
shadeSeparatingWrapper.clear(); shadeSeparatingWrapper.clear();
unshadedBuilder.end(); ShadeSeparatedBufferedData bufferedData = ModelUtil.endAndCombine(shadedBuilder, unshadedBuilder);
builder.appendUnshadedVertices(unshadedBuilder);
builder.end();
renderWorld.renderMode = false; renderWorld.renderMode = false;
return new SuperByteBuffer(builder); SuperByteBuffer sbb = new SuperByteBuffer(bufferedData);
bufferedData.release();
return sbb;
} }
private static int getLayerCount() { private static int getLayerCount() {
@ -146,6 +150,7 @@ public class SchematicRenderer {
public final Random random = new Random(); public final Random random = new Random();
public final BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); public final BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
public final ShadeSeparatingVertexConsumer shadeSeparatingWrapper = new ShadeSeparatingVertexConsumer(); public final ShadeSeparatingVertexConsumer shadeSeparatingWrapper = new ShadeSeparatingVertexConsumer();
public final BufferBuilder shadedBuilder = new BufferBuilder(512);
public final BufferBuilder unshadedBuilder = new BufferBuilder(512); public final BufferBuilder unshadedBuilder = new BufferBuilder(512);
} }

View file

@ -8,7 +8,7 @@ import java.util.Random;
import java.util.function.Consumer; import java.util.function.Consumer;
import com.jozufozu.flywheel.core.model.ModelUtil; 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.core.model.ShadeSeparatingVertexConsumer;
import com.jozufozu.flywheel.util.transform.TransformStack; import com.jozufozu.flywheel.util.transform.TransformStack;
import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.BufferBuilder;
@ -258,7 +258,7 @@ public class WorldSectionElement extends AnimatedSceneElement {
prevAnimatedRotation = animatedRotation; prevAnimatedRotation = animatedRotation;
if (!isVisible()) if (!isVisible())
return; return;
loadTEsIfMissing(scene.getWorld()); loadBEsIfMissing(scene.getWorld());
renderedBlockEntities.removeIf(be -> scene.getWorld() renderedBlockEntities.removeIf(be -> scene.getWorld()
.getBlockEntity(be.getBlockPos()) != be); .getBlockEntity(be.getBlockPos()) != be);
tickableBlockEntities.removeIf(be -> scene.getWorld() tickableBlockEntities.removeIf(be -> scene.getWorld()
@ -277,7 +277,7 @@ public class WorldSectionElement extends AnimatedSceneElement {
redraw = false; redraw = false;
} }
protected void loadTEsIfMissing(PonderWorld world) { protected void loadBEsIfMissing(PonderWorld world) {
if (renderedBlockEntities != null) if (renderedBlockEntities != null)
return; return;
tickableBlockEntities = new ArrayList<>(); tickableBlockEntities = new ArrayList<>();
@ -405,7 +405,7 @@ public class WorldSectionElement extends AnimatedSceneElement {
} }
private void renderBlockEntities(PonderWorld world, PoseStack ms, MultiBufferSource buffer, float pt) { private void renderBlockEntities(PonderWorld world, PoseStack ms, MultiBufferSource buffer, float pt) {
loadTEsIfMissing(world); loadBEsIfMissing(world);
BlockEntityRenderHelper.renderBlockEntities(world, renderedBlockEntities, ms, buffer, pt); BlockEntityRenderHelper.renderBlockEntities(world, renderedBlockEntities, ms, buffer, pt);
} }
@ -416,12 +416,12 @@ public class WorldSectionElement extends AnimatedSceneElement {
PoseStack poseStack = objects.poseStack; PoseStack poseStack = objects.poseStack;
Random random = objects.random; Random random = objects.random;
ShadeSeparatingVertexConsumer shadeSeparatingWrapper = objects.shadeSeparatingWrapper; ShadeSeparatingVertexConsumer shadeSeparatingWrapper = objects.shadeSeparatingWrapper;
ShadeSeparatedBufferBuilder builder = new ShadeSeparatedBufferBuilder(512); BufferBuilder shadedBuilder = objects.shadedBuilder;
BufferBuilder unshadedBuilder = objects.unshadedBuilder; 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); unshadedBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
shadeSeparatingWrapper.prepare(builder, unshadedBuilder); shadeSeparatingWrapper.prepare(shadedBuilder, unshadedBuilder);
world.setMask(this.section); world.setMask(this.section);
ForgeHooksClient.setRenderType(layer); ForgeHooksClient.setRenderType(layer);
@ -440,7 +440,7 @@ public class WorldSectionElement extends AnimatedSceneElement {
} }
if (!fluidState.isEmpty() && ItemBlockRenderTypes.canRenderInLayer(fluidState, layer)) if (!fluidState.isEmpty() && ItemBlockRenderTypes.canRenderInLayer(fluidState, layer))
dispatcher.renderLiquid(pos, world, builder, state, fluidState); dispatcher.renderLiquid(pos, world, shadedBuilder, state, fluidState);
poseStack.popPose(); poseStack.popPose();
}); });
@ -449,17 +449,18 @@ public class WorldSectionElement extends AnimatedSceneElement {
world.clearMask(); world.clearMask();
shadeSeparatingWrapper.clear(); shadeSeparatingWrapper.clear();
unshadedBuilder.end(); ShadeSeparatedBufferedData bufferedData = ModelUtil.endAndCombine(shadedBuilder, unshadedBuilder);
builder.appendUnshadedVertices(unshadedBuilder);
builder.end();
return new SuperByteBuffer(builder); SuperByteBuffer sbb = new SuperByteBuffer(bufferedData);
bufferedData.release();
return sbb;
} }
private static class ThreadLocalObjects { private static class ThreadLocalObjects {
public final PoseStack poseStack = new PoseStack(); public final PoseStack poseStack = new PoseStack();
public final Random random = new Random(); public final Random random = new Random();
public final ShadeSeparatingVertexConsumer shadeSeparatingWrapper = new ShadeSeparatingVertexConsumer(); public final ShadeSeparatingVertexConsumer shadeSeparatingWrapper = new ShadeSeparatingVertexConsumer();
public final BufferBuilder shadedBuilder = new BufferBuilder(512);
public final BufferBuilder unshadedBuilder = new BufferBuilder(512); public final BufferBuilder unshadedBuilder = new BufferBuilder(512);
} }

View file

@ -1,7 +1,7 @@
package com.simibubi.create.foundation.render; package com.simibubi.create.foundation.render;
import com.jozufozu.flywheel.core.model.ModelUtil; 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 com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -22,8 +22,10 @@ public class BakedModelRenderHelper {
} }
public static SuperByteBuffer standardModelRender(BakedModel model, BlockState referenceState, PoseStack ms) { public static SuperByteBuffer standardModelRender(BakedModel model, BlockState referenceState, PoseStack ms) {
BufferBuilder builder = ModelUtil.getBufferBuilder(model, referenceState, ms); ShadeSeparatedBufferedData data = ModelUtil.getBufferedData(model, referenceState, ms);
return new SuperByteBuffer(builder); SuperByteBuffer sbb = new SuperByteBuffer(data);
data.release();
return sbb;
} }
} }

View file

@ -6,16 +6,14 @@ import java.util.function.IntPredicate;
import com.jozufozu.flywheel.api.vertex.ShadedVertexList; import com.jozufozu.flywheel.api.vertex.ShadedVertexList;
import com.jozufozu.flywheel.api.vertex.VertexList; import com.jozufozu.flywheel.api.vertex.VertexList;
import com.jozufozu.flywheel.backend.ShadersModHandler; 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.core.vertex.BlockVertexList;
import com.jozufozu.flywheel.util.DiffuseLightCalculator; import com.jozufozu.flywheel.util.DiffuseLightCalculator;
import com.jozufozu.flywheel.util.transform.TStack; import com.jozufozu.flywheel.util.transform.TStack;
import com.jozufozu.flywheel.util.transform.Transform; import com.jozufozu.flywheel.util.transform.Transform;
import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.BufferBuilder.DrawState;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.blaze3d.vertex.VertexConsumer;
import com.mojang.datafixers.util.Pair;
import com.mojang.math.Matrix3f; import com.mojang.math.Matrix3f;
import com.mojang.math.Matrix4f; import com.mojang.math.Matrix4f;
import com.mojang.math.Quaternion; import com.mojang.math.Quaternion;
@ -41,7 +39,7 @@ public class SuperByteBuffer implements Transform<SuperByteBuffer>, TStack<Super
private final IntPredicate shadedPredicate; private final IntPredicate shadedPredicate;
// Vertex Position // Vertex Position
private final PoseStack transforms; private final PoseStack transforms = new PoseStack();
// Vertex Coloring // Vertex Coloring
private boolean shouldColor; private boolean shouldColor;
@ -69,23 +67,28 @@ public class SuperByteBuffer implements Transform<SuperByteBuffer>, TStack<Super
// Temporary // Temporary
private static final Long2IntMap WORLD_LIGHT_CACHE = new Long2IntOpenHashMap(); private static final Long2IntMap WORLD_LIGHT_CACHE = new Long2IntOpenHashMap();
public SuperByteBuffer(BufferBuilder buf) { public SuperByteBuffer(ByteBuffer vertexBuffer, BufferBuilder.DrawState drawState, int unshadedStartVertex) {
Pair<DrawState, ByteBuffer> pair = buf.popNextBuffer();
DrawState drawState = pair.getFirst();
ByteBuffer buffer = pair.getSecond();
int vertexCount = drawState.vertexCount(); int vertexCount = drawState.vertexCount();
int stride = drawState.format().getVertexSize(); int stride = drawState.format().getVertexSize();
if (buf instanceof ShadeSeparatedBufferBuilder separated) { ShadedVertexList template = new BlockVertexList.Shaded(vertexBuffer, vertexCount, stride, unshadedStartVertex);
ShadedVertexList template = new BlockVertexList.Shaded(buffer, vertexCount, stride, separated.getUnshadedStartVertex()); shadedPredicate = template::isShaded;
shadedPredicate = template::isShaded; this.template = template;
this.template = template;
} else { transforms.pushPose();
template = new BlockVertexList(buffer, vertexCount, stride); }
shadedPredicate = index -> true;
} 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(); transforms.pushPose();
} }
@ -246,6 +249,10 @@ public class SuperByteBuffer implements Transform<SuperByteBuffer>, TStack<Super
return template.isEmpty(); return template.isEmpty();
} }
public void delete() {
template.delete();
}
public PoseStack getTransforms() { public PoseStack getTransforms() {
return transforms; return transforms;
} }

View file

@ -15,12 +15,14 @@ public class SuperByteBufferCache {
public synchronized void registerCompartment(Compartment<?> compartment) { public synchronized void registerCompartment(Compartment<?> compartment) {
caches.put(compartment, CacheBuilder.newBuilder() caches.put(compartment, CacheBuilder.newBuilder()
.<Object, SuperByteBuffer>removalListener(n -> n.getValue().delete())
.build()); .build());
} }
public synchronized void registerCompartment(Compartment<?> compartment, long ticksUntilExpired) { public synchronized void registerCompartment(Compartment<?> compartment, long ticksUntilExpired) {
caches.put(compartment, CacheBuilder.newBuilder() caches.put(compartment, CacheBuilder.newBuilder()
.expireAfterAccess(ticksUntilExpired * 50, TimeUnit.MILLISECONDS) .expireAfterAccess(ticksUntilExpired * 50, TimeUnit.MILLISECONDS)
.<Object, SuperByteBuffer>removalListener(n -> n.getValue().delete())
.build()); .build());
} }