mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-12-26 15:06:28 +01:00
Fix poor design choices resulting in memory leaks
- Add ShadeSeparatedBufferedData which is returned by buffering utilities and can be released - Remove ShadeSeparatedBufferBuilder and add ModelUtil#endAndCombine - Add VertexList#delete - Replace all usage of MemoryTracker with MemoryUtil - Add FlwUtil#copyBuffer - Turn most BlockModel constructors into static methods - Add BakedModelBuilder#toModel
This commit is contained in:
parent
873facfd34
commit
e79f6bcbf6
14 changed files with 188 additions and 131 deletions
|
@ -25,11 +25,11 @@ public interface Material<D extends InstanceData> {
|
|||
Instancer<D> model(Object key, Supplier<Model> modelSupplier);
|
||||
|
||||
default Instancer<D> getModel(PartialModel partial, BlockState referenceState) {
|
||||
return model(partial, () -> new BlockModel(partial.get(), referenceState));
|
||||
return model(partial, () -> BlockModel.of(partial.get(), referenceState));
|
||||
}
|
||||
|
||||
default Instancer<D> getModel(PartialModel partial) {
|
||||
return model(partial, () -> new BlockModel(partial.get(), Blocks.AIR.defaultBlockState()));
|
||||
return model(partial, () -> BlockModel.of(partial.get(), Blocks.AIR.defaultBlockState()));
|
||||
}
|
||||
|
||||
default Instancer<D> getModel(PartialModel partial, BlockState referenceState, Direction dir) {
|
||||
|
@ -37,10 +37,10 @@ public interface Material<D extends InstanceData> {
|
|||
}
|
||||
|
||||
default Instancer<D> getModel(PartialModel partial, BlockState referenceState, Direction dir, Supplier<PoseStack> modelTransform) {
|
||||
return model(Pair.of(dir, partial), () -> new BlockModel(partial.get(), referenceState, modelTransform.get()));
|
||||
return model(Pair.of(dir, partial), () -> BlockModel.of(partial.get(), referenceState, modelTransform.get()));
|
||||
}
|
||||
|
||||
default Instancer<D> getModel(BlockState toRender) {
|
||||
return model(toRender, () -> new BlockModel(toRender));
|
||||
return model(toRender, () -> BlockModel.of(toRender));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,4 +41,7 @@ public interface VertexList {
|
|||
default boolean isEmpty() {
|
||||
return getVertexCount() == 0;
|
||||
}
|
||||
|
||||
default void delete() {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,10 +3,10 @@ package com.jozufozu.flywheel.backend.instancing;
|
|||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import com.jozufozu.flywheel.backend.model.BufferBuilderExtension;
|
||||
import com.jozufozu.flywheel.backend.model.DirectVertexConsumer;
|
||||
import com.mojang.blaze3d.platform.MemoryTracker;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
|
@ -48,10 +48,10 @@ public class DrawBuffer {
|
|||
int byteSize = format.getVertexSize() * (vertexCount + 1);
|
||||
|
||||
if (backingBuffer == null) {
|
||||
backingBuffer = MemoryTracker.create(byteSize);
|
||||
backingBuffer = MemoryUtil.memAlloc(byteSize);
|
||||
}
|
||||
if (byteSize > backingBuffer.capacity()) {
|
||||
backingBuffer = MemoryTracker.resize(backingBuffer, byteSize);
|
||||
backingBuffer = MemoryUtil.memRealloc(backingBuffer, byteSize);
|
||||
}
|
||||
|
||||
return new DirectVertexConsumer(backingBuffer, format, vertexCount);
|
||||
|
|
|
@ -10,7 +10,6 @@ import com.jozufozu.flywheel.api.vertex.VertexType;
|
|||
import com.jozufozu.flywheel.core.Formats;
|
||||
import com.jozufozu.flywheel.core.model.Model;
|
||||
import com.jozufozu.flywheel.core.vertex.PosTexNormalWriterUnsafe;
|
||||
import com.mojang.blaze3d.platform.MemoryTracker;
|
||||
|
||||
public class ModelPart implements Model {
|
||||
|
||||
|
@ -29,7 +28,7 @@ public class ModelPart implements Model {
|
|||
this.vertices = vertices;
|
||||
}
|
||||
|
||||
ByteBuffer buffer = MemoryTracker.create(size());
|
||||
ByteBuffer buffer = MemoryUtil.memAlloc(size());
|
||||
PosTexNormalWriterUnsafe writer = Formats.POS_TEX_NORMAL.createWriter(buffer);
|
||||
for (PartBuilder.CuboidBuilder cuboid : cuboids) {
|
||||
cuboid.buffer(writer);
|
||||
|
@ -65,12 +64,6 @@ public class ModelPart implements Model {
|
|||
|
||||
@Override
|
||||
public void delete() {
|
||||
if (reader instanceof AutoCloseable closeable) {
|
||||
try {
|
||||
closeable.close();
|
||||
} catch (Exception e) {
|
||||
//
|
||||
}
|
||||
}
|
||||
reader.delete();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,15 @@ public final class BakedModelBuilder implements Bufferable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void bufferInto(ModelBlockRenderer blockRenderer, VertexConsumer consumer, Random random) {
|
||||
public void bufferInto(VertexConsumer consumer, ModelBlockRenderer blockRenderer, Random random) {
|
||||
blockRenderer.tesselateBlock(renderWorld, model, referenceState, BlockPos.ZERO, poseStack, consumer, false, random, 42, OverlayTexture.NO_OVERLAY, VirtualEmptyModelData.INSTANCE);
|
||||
}
|
||||
|
||||
public BlockModel toModel(String name) {
|
||||
return BlockModel.of(this, name);
|
||||
}
|
||||
|
||||
public BlockModel toModel() {
|
||||
return toModel(referenceState.toString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
package com.jozufozu.flywheel.core.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.jozufozu.flywheel.api.vertex.VertexList;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.core.Formats;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
@ -17,28 +21,55 @@ public class BlockModel implements Model {
|
|||
private final VertexList reader;
|
||||
private final String name;
|
||||
|
||||
public BlockModel(BlockState state) {
|
||||
this(Minecraft.getInstance()
|
||||
public BlockModel(ByteBuffer vertexBuffer, BufferBuilder.DrawState drawState, int unshadedStartVertex, String name) {
|
||||
if (drawState.format() != DefaultVertexFormat.BLOCK) {
|
||||
throw new RuntimeException("Cannot use buffered data with non-block format '" + drawState.format() + "'");
|
||||
}
|
||||
|
||||
reader = Formats.BLOCK.createReader(vertexBuffer, drawState.vertexCount(), unshadedStartVertex);
|
||||
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public BlockModel(ByteBuffer vertexBuffer, BufferBuilder.DrawState drawState, String name) {
|
||||
if (drawState.format() != DefaultVertexFormat.BLOCK) {
|
||||
throw new RuntimeException("Cannot use buffered data with non-block format '" + drawState.format() + "'");
|
||||
}
|
||||
|
||||
reader = Formats.BLOCK.createReader(vertexBuffer, drawState.vertexCount());
|
||||
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public BlockModel(ShadeSeparatedBufferedData data, String name) {
|
||||
this(data.vertexBuffer(), data.drawState(), data.unshadedStartVertex(), name);
|
||||
}
|
||||
|
||||
public static BlockModel of(Bufferable bufferable, String name) {
|
||||
ShadeSeparatedBufferedData data = bufferable.build();
|
||||
BlockModel model = new BlockModel(data, name);
|
||||
data.release();
|
||||
return model;
|
||||
}
|
||||
|
||||
public static BlockModel of(BakedModel model, BlockState referenceState) {
|
||||
ShadeSeparatedBufferedData data = ModelUtil.getBufferedData(model, referenceState);
|
||||
BlockModel blockModel = new BlockModel(data, referenceState.toString());
|
||||
data.release();
|
||||
return blockModel;
|
||||
}
|
||||
|
||||
public static BlockModel of(BlockState state) {
|
||||
return of(Minecraft.getInstance()
|
||||
.getBlockRenderer()
|
||||
.getBlockModel(state), state);
|
||||
}
|
||||
|
||||
public BlockModel(BakedModel model, BlockState referenceState) {
|
||||
this(new BakedModelBuilder(model).withReferenceState(referenceState), referenceState.toString());
|
||||
}
|
||||
|
||||
public BlockModel(BakedModel model, BlockState referenceState, PoseStack ms) {
|
||||
this(new BakedModelBuilder(model).withReferenceState(referenceState)
|
||||
.withPoseStack(ms), referenceState.toString());
|
||||
}
|
||||
|
||||
public BlockModel(Bufferable bufferable, String name) {
|
||||
this(bufferable.build(), name);
|
||||
}
|
||||
|
||||
public BlockModel(ShadeSeparatedBufferBuilder bufferBuilder, String name) {
|
||||
this.name = name;
|
||||
reader = Formats.BLOCK.createReader(bufferBuilder);
|
||||
public static BlockModel of(BakedModel model, BlockState referenceState, PoseStack ms) {
|
||||
ShadeSeparatedBufferedData data = ModelUtil.getBufferedData(model, referenceState, ms);
|
||||
BlockModel blockModel = new BlockModel(data, referenceState.toString());
|
||||
data.release();
|
||||
return blockModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -63,12 +94,6 @@ public class BlockModel implements Model {
|
|||
|
||||
@Override
|
||||
public void delete() {
|
||||
if (reader instanceof AutoCloseable closeable) {
|
||||
try {
|
||||
closeable.close();
|
||||
} catch (Exception e) {
|
||||
//
|
||||
}
|
||||
}
|
||||
reader.delete();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,12 +8,12 @@ import com.mojang.blaze3d.vertex.VertexConsumer;
|
|||
import net.minecraft.client.renderer.block.ModelBlockRenderer;
|
||||
|
||||
/**
|
||||
* An interface for objects that can "rendered" into a BufferBuilder.
|
||||
* An interface for objects that can buffered into a VertexConsumer.
|
||||
*/
|
||||
public interface Bufferable {
|
||||
void bufferInto(ModelBlockRenderer renderer, VertexConsumer consumer, Random random);
|
||||
void bufferInto(VertexConsumer consumer, ModelBlockRenderer renderer, Random random);
|
||||
|
||||
default ShadeSeparatedBufferBuilder build() {
|
||||
return ModelUtil.getBufferBuilder(this);
|
||||
default ShadeSeparatedBufferedData build() {
|
||||
return ModelUtil.getBufferedData(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
package com.jozufozu.flywheel.core.model;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Collection;
|
||||
import java.util.Random;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.backend.model.BufferBuilderExtension;
|
||||
import com.jozufozu.flywheel.util.transform.TransformStack;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder.DrawState;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
|
@ -48,39 +52,52 @@ public class ModelUtil {
|
|||
return dispatcher;
|
||||
}
|
||||
|
||||
public static ShadeSeparatedBufferBuilder getBufferBuilder(Bufferable bufferable) {
|
||||
public static ShadeSeparatedBufferedData endAndCombine(BufferBuilder shadedBuilder, BufferBuilder unshadedBuilder) {
|
||||
int unshadedStartVertex = ((BufferBuilderExtension) shadedBuilder).flywheel$getVertices();
|
||||
unshadedBuilder.end();
|
||||
Pair<DrawState, ByteBuffer> unshadedData = unshadedBuilder.popNextBuffer();
|
||||
((BufferBuilderExtension) shadedBuilder).flywheel$appendBufferUnsafe(unshadedData.getSecond());
|
||||
shadedBuilder.end();
|
||||
Pair<DrawState, ByteBuffer> data = shadedBuilder.popNextBuffer();
|
||||
return new ShadeSeparatedBufferedData.NativeImpl(data.getSecond(), data.getFirst(), unshadedStartVertex);
|
||||
}
|
||||
|
||||
public static ShadeSeparatedBufferedData getBufferedData(Bufferable bufferable) {
|
||||
ModelBlockRenderer blockRenderer = VANILLA_RENDERER.getModelRenderer();
|
||||
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
|
||||
|
||||
objects.begin();
|
||||
|
||||
bufferable.bufferInto(blockRenderer, objects.shadeSeparatingWrapper, objects.random);
|
||||
bufferable.bufferInto(objects.shadeSeparatingWrapper, blockRenderer, objects.random);
|
||||
|
||||
objects.end();
|
||||
|
||||
return objects.separatedBufferBuilder;
|
||||
return objects.end();
|
||||
}
|
||||
|
||||
public static ShadeSeparatedBufferBuilder getBufferBuilder(BakedModel model, BlockState referenceState, PoseStack poseStack) {
|
||||
public static ShadeSeparatedBufferedData getBufferedData(BakedModel model, BlockState referenceState) {
|
||||
return new BakedModelBuilder(model).withReferenceState(referenceState)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static ShadeSeparatedBufferedData getBufferedData(BakedModel model, BlockState referenceState, PoseStack poseStack) {
|
||||
return new BakedModelBuilder(model).withReferenceState(referenceState)
|
||||
.withPoseStack(poseStack)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static ShadeSeparatedBufferBuilder getBufferBuilder(BlockAndTintGetter renderWorld, BakedModel model, BlockState referenceState, PoseStack poseStack) {
|
||||
public static ShadeSeparatedBufferedData getBufferedData(BlockAndTintGetter renderWorld, BakedModel model, BlockState referenceState, PoseStack poseStack) {
|
||||
return new BakedModelBuilder(model).withReferenceState(referenceState)
|
||||
.withPoseStack(poseStack)
|
||||
.withRenderWorld(renderWorld)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static ShadeSeparatedBufferBuilder getBufferBuilderFromTemplate(BlockAndTintGetter renderWorld, RenderType layer, Collection<StructureTemplate.StructureBlockInfo> blocks) {
|
||||
public static ShadeSeparatedBufferedData getBufferedDataFromTemplate(BlockAndTintGetter renderWorld, RenderType layer, Collection<StructureTemplate.StructureBlockInfo> blocks) {
|
||||
return new WorldModelBuilder(layer).withRenderWorld(renderWorld)
|
||||
.withBlocks(blocks)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static ShadeSeparatedBufferBuilder getBufferBuilderFromTemplate(BlockAndTintGetter renderWorld, RenderType layer, Collection<StructureTemplate.StructureBlockInfo> blocks, PoseStack poseStack) {
|
||||
public static ShadeSeparatedBufferedData getBufferedDataFromTemplate(BlockAndTintGetter renderWorld, RenderType layer, Collection<StructureTemplate.StructureBlockInfo> blocks, PoseStack poseStack) {
|
||||
return new WorldModelBuilder(layer).withRenderWorld(renderWorld)
|
||||
.withBlocks(blocks)
|
||||
.withPoseStack(poseStack)
|
||||
|
@ -101,20 +118,18 @@ public class ModelUtil {
|
|||
private static class ThreadLocalObjects {
|
||||
public final Random random = new Random();
|
||||
public final ShadeSeparatingVertexConsumer shadeSeparatingWrapper = new ShadeSeparatingVertexConsumer();
|
||||
public final ShadeSeparatedBufferBuilder separatedBufferBuilder = new ShadeSeparatedBufferBuilder(512);
|
||||
public final BufferBuilder shadedBuilder = new BufferBuilder(512);
|
||||
public final BufferBuilder unshadedBuilder = new BufferBuilder(512);
|
||||
|
||||
private void begin() {
|
||||
this.separatedBufferBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
||||
this.shadedBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
||||
this.unshadedBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
||||
this.shadeSeparatingWrapper.prepare(this.separatedBufferBuilder, this.unshadedBuilder);
|
||||
this.shadeSeparatingWrapper.prepare(this.shadedBuilder, this.unshadedBuilder);
|
||||
}
|
||||
|
||||
private void end() {
|
||||
private ShadeSeparatedBufferedData end() {
|
||||
this.shadeSeparatingWrapper.clear();
|
||||
this.unshadedBuilder.end();
|
||||
this.separatedBufferBuilder.appendUnshadedVertices(this.unshadedBuilder);
|
||||
this.separatedBufferBuilder.end();
|
||||
return ModelUtil.endAndCombine(shadedBuilder, unshadedBuilder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
package com.jozufozu.flywheel.core.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.jozufozu.flywheel.backend.model.BufferBuilderExtension;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
|
||||
public class ShadeSeparatedBufferBuilder extends BufferBuilder {
|
||||
protected int unshadedStartVertex;
|
||||
|
||||
public ShadeSeparatedBufferBuilder(int capacity) {
|
||||
super(capacity);
|
||||
}
|
||||
|
||||
public void appendUnshadedVertices(BufferBuilder unshadedBuilder) {
|
||||
Pair<DrawState, ByteBuffer> data = unshadedBuilder.popNextBuffer();
|
||||
unshadedStartVertex = ((BufferBuilderExtension) this).flywheel$getVertices();
|
||||
((BufferBuilderExtension) this).flywheel$appendBufferUnsafe(data.getSecond());
|
||||
}
|
||||
|
||||
public int getUnshadedStartVertex() {
|
||||
return unshadedStartVertex;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package com.jozufozu.flywheel.core.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import com.jozufozu.flywheel.util.FlwUtil;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder.DrawState;
|
||||
|
||||
public interface ShadeSeparatedBufferedData {
|
||||
ByteBuffer vertexBuffer();
|
||||
|
||||
BufferBuilder.DrawState drawState();
|
||||
|
||||
int unshadedStartVertex();
|
||||
|
||||
void release();
|
||||
|
||||
static final class NativeImpl implements ShadeSeparatedBufferedData {
|
||||
private final ByteBuffer vertexBuffer;
|
||||
private final BufferBuilder.DrawState drawState;
|
||||
private final int unshadedStartVertex;
|
||||
|
||||
public NativeImpl(ByteBuffer vertexBuffer, BufferBuilder.DrawState drawState, int unshadedStartVertex) {
|
||||
this.vertexBuffer = FlwUtil.copyBuffer(vertexBuffer);
|
||||
this.drawState = drawState;
|
||||
this.unshadedStartVertex = unshadedStartVertex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer vertexBuffer() {
|
||||
return vertexBuffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DrawState drawState() {
|
||||
return drawState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int unshadedStartVertex() {
|
||||
return unshadedStartVertex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
MemoryUtil.memFree(vertexBuffer);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -35,7 +35,7 @@ public final class WorldModelBuilder implements Bufferable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void bufferInto(ModelBlockRenderer modelRenderer, VertexConsumer consumer, Random random) {
|
||||
public void bufferInto(VertexConsumer consumer, ModelBlockRenderer modelRenderer, Random random) {
|
||||
ForgeHooksClient.setRenderType(this.layer);
|
||||
ModelBlockRenderer.enableCaching();
|
||||
for (StructureTemplate.StructureBlockInfo info : this.blocks) {
|
||||
|
@ -80,7 +80,7 @@ public final class WorldModelBuilder implements Bufferable {
|
|||
return this;
|
||||
}
|
||||
|
||||
public BlockModel intoMesh(String name) {
|
||||
return new BlockModel(this, name);
|
||||
public BlockModel toModel(String name) {
|
||||
return BlockModel.of(this, name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,39 +1,31 @@
|
|||
package com.jozufozu.flywheel.core.vertex;
|
||||
|
||||
import java.nio.Buffer;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import com.jozufozu.flywheel.api.vertex.VertexList;
|
||||
import com.mojang.blaze3d.platform.MemoryTracker;
|
||||
import com.jozufozu.flywheel.util.FlwUtil;
|
||||
|
||||
public abstract class AbstractVertexList implements VertexList, AutoCloseable {
|
||||
public abstract class AbstractVertexList implements VertexList {
|
||||
|
||||
protected final ByteBuffer contents;
|
||||
protected final long base;
|
||||
protected final int vertexCount;
|
||||
|
||||
protected AbstractVertexList(ByteBuffer copyFrom, int vertexCount) {
|
||||
this.contents = MemoryTracker.create(copyFrom.capacity());
|
||||
this.contents = FlwUtil.copyBuffer(copyFrom);
|
||||
this.vertexCount = vertexCount;
|
||||
this.base = MemoryUtil.memAddress(this.contents);
|
||||
init(copyFrom);
|
||||
}
|
||||
|
||||
private void init(ByteBuffer copyFrom) {
|
||||
this.contents.order(copyFrom.order());
|
||||
this.contents.put(copyFrom);
|
||||
((Buffer) this.contents).flip();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
MemoryUtil.memFree(contents);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVertexCount() {
|
||||
return vertexCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
MemoryUtil.memFree(contents);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,14 +2,9 @@ package com.jozufozu.flywheel.core.vertex;
|
|||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.jozufozu.flywheel.api.vertex.VertexList;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||
import com.jozufozu.flywheel.core.layout.CommonItems;
|
||||
import com.jozufozu.flywheel.core.model.ShadeSeparatedBufferBuilder;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
|
||||
public class BlockVertex implements VertexType {
|
||||
|
||||
|
@ -37,6 +32,10 @@ public class BlockVertex implements VertexType {
|
|||
return new BlockVertexListUnsafe(buffer, vertexCount);
|
||||
}
|
||||
|
||||
public BlockVertexListUnsafe.Shaded createReader(ByteBuffer buffer, int vertexCount, int unshadedStartVertex) {
|
||||
return new BlockVertexListUnsafe.Shaded(buffer, vertexCount, unshadedStartVertex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getShaderHeader() {
|
||||
return """
|
||||
|
@ -57,24 +56,4 @@ Vertex FLWCreateVertex() {
|
|||
}
|
||||
""";
|
||||
}
|
||||
|
||||
public BlockVertexListUnsafe.Shaded createReader(ByteBuffer buffer, int vertexCount, int unshadedStartVertex) {
|
||||
return new BlockVertexListUnsafe.Shaded(buffer, vertexCount, unshadedStartVertex);
|
||||
}
|
||||
|
||||
public VertexList createReader(BufferBuilder bufferBuilder) {
|
||||
// TODO: try to avoid virtual model rendering
|
||||
Pair<BufferBuilder.DrawState, ByteBuffer> pair = bufferBuilder.popNextBuffer();
|
||||
BufferBuilder.DrawState drawState = pair.getFirst();
|
||||
|
||||
if (drawState.format() != DefaultVertexFormat.BLOCK) {
|
||||
throw new RuntimeException("Cannot use BufferBuilder with " + drawState.format());
|
||||
}
|
||||
|
||||
if (bufferBuilder instanceof ShadeSeparatedBufferBuilder separated) {
|
||||
return createReader(pair.getSecond(), drawState.vertexCount(), separated.getUnshadedStartVertex());
|
||||
} else {
|
||||
return createReader(pair.getSecond(), drawState.vertexCount());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
package com.jozufozu.flywheel.util;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import com.jozufozu.flywheel.mixin.BlockEntityRenderDispatcherAccessor;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
@ -73,4 +76,17 @@ public class FlwUtil {
|
|||
public static <R> Stream<R> mapValues(Map<?, R> map) {
|
||||
return map.values().stream();
|
||||
}
|
||||
|
||||
/**
|
||||
* The returned buffer is backed by native memory and will cause a memory leak if not freed using {@link MemoryUtil#memFree(java.nio.Buffer)}.
|
||||
*/
|
||||
public static ByteBuffer copyBuffer(ByteBuffer buffer) {
|
||||
int pos = buffer.position();
|
||||
ByteBuffer copy = MemoryUtil.memAlloc(buffer.remaining());
|
||||
copy.order(buffer.order());
|
||||
copy.put(buffer);
|
||||
buffer.position(pos);
|
||||
copy.flip();
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue