Wait, it's all unsafe? Always has been.

- Create MemoryBlock utility for easier management of memory allocation
- Replace most usage of direct ByteBuffer with MemoryBlock
- Remove all usage of Mojang's MemoryTracker
- Simplifier StructWriter
- Rename some classes and packages
This commit is contained in:
PepperCode1 2022-08-10 20:47:53 -07:00
parent 6913a34443
commit f0823af00f
42 changed files with 445 additions and 350 deletions

View file

@ -1,7 +1,5 @@
package com.jozufozu.flywheel.api.struct;
import java.nio.ByteBuffer;
import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.core.layout.BufferLayout;
@ -25,16 +23,11 @@ public interface StructType<S extends InstancedPart> {
*/
BufferLayout getLayout();
/**
* Create a {@link StructWriter} that will consume instances of S and write them to the given buffer.
*
* @param backing The buffer that the StructWriter will write to.
*/
StructWriter<S> getWriter(ByteBuffer backing);
StructWriter<S> getWriter();
FileResolution getInstanceShader();
VertexTransformer<? extends S> getVertexTransformer();
VertexTransformer<S> getVertexTransformer();
public interface VertexTransformer<S extends InstancedPart> {
void transform(MutableVertexList vertexList, S struct, ClientLevel level);

View file

@ -1,17 +1,13 @@
package com.jozufozu.flywheel.api.struct;
import com.jozufozu.flywheel.api.instancer.InstancedPart;
/**
* StructWriters can quickly consume many instances of S and write them to some backing buffer.
*/
public interface StructWriter<S> {
public interface StructWriter<S extends InstancedPart> {
/**
* Write the given struct to the backing array.
* Write the given struct to given memory address.
*/
void write(S struct);
/**
* Seek to the given position. The next write will occur there.
*/
void seek(int pos);
void write(long ptr, S struct);
}

View file

@ -1,57 +0,0 @@
package com.jozufozu.flywheel.backend;
import java.lang.ref.Cleaner;
import java.nio.ByteBuffer;
import org.lwjgl.system.MemoryUtil;
public class FlywheelMemory {
public static final Cleaner CLEANER = Cleaner.create();
private static int gpuMemory = 0;
private static int cpuMemory = 0;
public static void _freeCPUMemory(long size) {
cpuMemory -= size;
}
public static void _allocCPUMemory(long size) {
cpuMemory += size;
}
public static void _freeGPUMemory(long size) {
gpuMemory -= size;
}
public static void _allocGPUMemory(long size) {
gpuMemory += size;
}
public static int getGPUMemory() {
return gpuMemory;
}
public static int getCPUMemory() {
return cpuMemory;
}
public static Cleaner.Cleanable track(Object owner, ByteBuffer buffer) {
return CLEANER.register(owner, new Tracked(buffer));
}
public static class Tracked implements Runnable {
private final ByteBuffer buffer;
public Tracked(ByteBuffer buffer) {
this.buffer = buffer;
_allocCPUMemory(buffer.capacity());
}
public void run() {
_freeCPUMemory(buffer.capacity());
MemoryUtil.memFree(buffer);
}
}
}

View file

@ -8,7 +8,6 @@ import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL20C;
import org.lwjgl.opengl.GLCapabilities;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil;
import net.minecraft.Util;
@ -75,7 +74,7 @@ public class GlCompat {
}
/**
* Copied from:
* Modified from:
* <br> <a href="https://github.com/grondag/canvas/commit/820bf754092ccaf8d0c169620c2ff575722d7d96">canvas</a>
*
* <p>Identical in function to {@link GL20C#glShaderSource(int, CharSequence)} but
@ -87,18 +86,11 @@ public class GlCompat {
* <p>Hat tip to fewizz for the find and the fix.
*/
public static void safeShaderSource(int glId, CharSequence source) {
final MemoryStack stack = MemoryStack.stackGet();
final int stackPointer = stack.getPointer();
try {
final ByteBuffer sourceBuffer = MemoryUtil.memUTF8(source, true);
try (MemoryStack stack = MemoryStack.stackPush()) {
final ByteBuffer sourceBuffer = stack.UTF8(source, true);
final PointerBuffer pointers = stack.mallocPointer(1);
pointers.put(sourceBuffer);
GL20C.nglShaderSource(glId, 1, pointers.address0(), 0);
org.lwjgl.system.APIUtil.apiArrayFree(pointers.address0(), 1);
} finally {
stack.setPointer(stackPointer);
}
}

View file

@ -2,12 +2,10 @@ package com.jozufozu.flywheel.backend.instancing.batching;
import java.nio.ByteBuffer;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
import com.jozufozu.flywheel.api.vertex.VertexListProvider;
import com.jozufozu.flywheel.backend.memory.MemoryBlock;
import com.jozufozu.flywheel.core.vertex.VertexListProviderRegistry;
import com.mojang.blaze3d.platform.MemoryTracker;
import com.mojang.blaze3d.vertex.VertexFormat;
import net.minecraft.client.renderer.RenderType;
@ -23,9 +21,10 @@ public class DrawBuffer {
private final int stride;
private final VertexListProvider provider;
private ByteBuffer backingBuffer;
private MemoryBlock memory;
private ByteBuffer buffer;
private int expectedVertices;
private long ptr;
public DrawBuffer(RenderType parent) {
this.parent = parent;
@ -41,7 +40,7 @@ public class DrawBuffer {
*/
public void prepare(int vertexCount) {
if (expectedVertices != 0) {
throw new IllegalStateException("Already drawing");
throw new IllegalStateException("Already drawing!");
}
this.expectedVertices = vertexCount;
@ -51,20 +50,20 @@ public class DrawBuffer {
// is called and reallocates the buffer if there is not space for one more vertex.
int byteSize = stride * (vertexCount + 1);
if (backingBuffer == null) {
backingBuffer = MemoryTracker.create(byteSize);
} else if (byteSize > backingBuffer.capacity()) {
backingBuffer = MemoryTracker.resize(backingBuffer, byteSize);
if (memory == null) {
memory = MemoryBlock.malloc(byteSize);
buffer = memory.asBuffer();
} else if (byteSize > memory.size()) {
memory = memory.realloc(byteSize);
buffer = memory.asBuffer();
}
backingBuffer.clear();
ptr = MemoryUtil.memAddress(backingBuffer);
MemoryUtil.memSet(ptr, 0, byteSize);
memory.clear();
}
public ReusableVertexList slice(int startVertex, int vertexCount) {
ReusableVertexList vertexList = provider.createVertexList();
vertexList.ptr(ptr + startVertex * stride);
vertexList.ptr(memory.ptr() + startVertex * stride);
vertexList.setVertexCount(vertexCount);
return vertexList;
}
@ -74,7 +73,8 @@ public class DrawBuffer {
* @param bufferBuilder The buffer builder to inject into.
*/
public void inject(BufferBuilderExtension bufferBuilder) {
bufferBuilder.flywheel$injectForRender(backingBuffer, format, expectedVertices);
buffer.clear();
bufferBuilder.flywheel$injectForRender(buffer, format, expectedVertices);
}
public int getVertexCount() {
@ -96,4 +96,9 @@ public class DrawBuffer {
public void reset() {
this.expectedVertices = 0;
}
public void free() {
buffer = null;
memory.free();
}
}

View file

@ -5,7 +5,6 @@ import java.util.List;
import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.struct.StructType.VertexTransformer;
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
import com.jozufozu.flywheel.backend.instancing.TaskEngine;
@ -71,11 +70,10 @@ public class TransformSet<D extends InstancedPart> {
int meshVertexCount = mesh.getVertexCount();
vertexList.setVertexCount(meshVertexCount);
@SuppressWarnings("unchecked")
StructType.VertexTransformer<D> structVertexTransformer = (VertexTransformer<D>) instancer.type.getVertexTransformer();
StructType.VertexTransformer<D> structVertexTransformer = instancer.type.getVertexTransformer();
for (D d : list) {
mesh.writeInto(vertexList);
mesh.write(vertexList);
structVertexTransformer.transform(vertexList, d, level);

View file

@ -10,8 +10,8 @@ import com.jozufozu.flywheel.api.instancer.InstancerFactory;
import com.jozufozu.flywheel.api.instancer.InstancerManager;
import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
import com.jozufozu.flywheel.core.structs.StructTypes;
import com.jozufozu.flywheel.core.structs.model.TransformedPart;
import com.jozufozu.flywheel.core.structs.oriented.OrientedPart;
import com.jozufozu.flywheel.core.structs.transformed.TransformedPart;
import com.jozufozu.flywheel.util.box.GridAlignedBB;
import com.jozufozu.flywheel.util.box.ImmutableBox;

View file

@ -3,6 +3,8 @@ package com.jozufozu.flywheel.backend.instancing.instancing;
import java.util.HashSet;
import java.util.Set;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.struct.StructType;
@ -89,20 +91,14 @@ public class GPUInstancer<D extends InstancedPart> extends AbstractInstancer<D>
buf.clear(clearStart, clearLength);
if (size > 0) {
final long ptr = MemoryUtil.memAddress(buf.unwrap());
final int stride = structType.getLayout().getStride();
final StructWriter<D> writer = structType.getWriter();
final StructWriter<D> writer = structType.getWriter(buf.unwrap());
boolean sequential = true;
for (int i = 0; i < size; i++) {
final D element = data.get(i);
if (element.checkDirtyAndClear()) {
if (!sequential) {
writer.seek(i);
}
writer.write(element);
sequential = true;
} else {
sequential = false;
writer.write(ptr + i * stride, element);
}
}
}

View file

@ -10,6 +10,7 @@ import java.util.Set;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.opengl.GL32;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.vertex.VertexType;
@ -240,7 +241,9 @@ public class MeshPool {
}
private void buffer(ByteBuffer buffer) {
this.mesh.writeInto(buffer, this.byteIndex);
buffer.position((int) this.byteIndex);
long ptr = MemoryUtil.memAddress(buffer);
this.mesh.write(ptr);
this.boundTo.clear();
this.gpuResident = true;

View file

@ -0,0 +1,141 @@
package com.jozufozu.flywheel.backend.memory;
import java.lang.ref.Cleaner;
import java.nio.ByteBuffer;
import org.lwjgl.system.MemoryUtil;
public class FlwMemoryTracker {
private static final Cleaner CLEANER = Cleaner.create();
private static long cpuMemory = 0;
private static long gpuMemory = 0;
public static long malloc(long size) {
long ptr = MemoryUtil.nmemAlloc(size);
if (ptr == MemoryUtil.NULL) {
throw new OutOfMemoryError("Failed to allocate " + size + " bytes");
}
return ptr;
}
public static MemoryBlock mallocBlock(long size) {
MemoryBlock block = new MemoryBlockImpl(malloc(size), size);
cpuMemory += block.size();
return block;
}
public static MemoryBlock mallocBlockTracked(long size) {
TrackedMemoryBlockImpl block = new TrackedMemoryBlockImpl(malloc(size), size);
block.cleanable = CLEANER.register(block, () -> {
if (!block.isFreed()) {
block.free();
}
});
cpuMemory += block.size();
return block;
}
@Deprecated
public static ByteBuffer mallocBuffer(int size) {
ByteBuffer buffer = MemoryUtil.memByteBuffer(malloc(size), size);
cpuMemory += buffer.capacity();
return buffer;
}
public static long calloc(long num, long size) {
long ptr = MemoryUtil.nmemCalloc(num, size);
if (ptr == MemoryUtil.NULL) {
throw new OutOfMemoryError("Failed to allocate " + num + " blocks of size " + size + " bytes");
}
return ptr;
}
public static MemoryBlock callocBlock(long num, long size) {
MemoryBlock block = new MemoryBlockImpl(calloc(num, size), num * size);
cpuMemory += block.size();
return block;
}
public static MemoryBlock callocBlockTracked(long num, long size) {
TrackedMemoryBlockImpl block = new TrackedMemoryBlockImpl(calloc(num, size), num * size);
block.cleanable = CLEANER.register(block, () -> {
if (!block.isFreed()) {
block.free();
}
});
cpuMemory += block.size();
return block;
}
public static long realloc(long ptr, long size) {
ptr = MemoryUtil.nmemRealloc(ptr, size);
if (ptr == MemoryUtil.NULL) {
throw new OutOfMemoryError("Failed to reallocate " + size + " bytes for address 0x" + Long.toHexString(ptr));
}
return ptr;
}
public static MemoryBlock reallocBlock(MemoryBlock block, long size) {
MemoryBlock newBlock = new MemoryBlockImpl(realloc(block.ptr(), size), size);
cpuMemory += -block.size() + newBlock.size();
return newBlock;
}
public static MemoryBlock reallocBlockTracked(MemoryBlock block, long size) {
TrackedMemoryBlockImpl newBlock = new TrackedMemoryBlockImpl(realloc(block.ptr(), size), size);
newBlock.cleanable = CLEANER.register(newBlock, () -> {
if (!newBlock.isFreed()) {
newBlock.free();
}
});
cpuMemory += -block.size() + newBlock.size();
return newBlock;
}
@Deprecated
public static ByteBuffer reallocBuffer(ByteBuffer buffer, int size) {
ByteBuffer newBuffer = MemoryUtil.memByteBuffer(realloc(MemoryUtil.memAddress(buffer), size), size);
cpuMemory += -buffer.capacity() + newBuffer.capacity();
return newBuffer;
}
public static void free(long ptr) {
MemoryUtil.nmemFree(ptr);
}
public static void freeBlock(MemoryBlock block) {
free(block.ptr());
cpuMemory -= block.size();
}
@Deprecated
public static void freeBuffer(ByteBuffer buffer) {
free(MemoryUtil.memAddress(buffer));
cpuMemory -= buffer.capacity();
}
public static void _allocCPUMemory(long size) {
cpuMemory += size;
}
public static void _freeCPUMemory(long size) {
cpuMemory -= size;
}
public static void _allocGPUMemory(long size) {
gpuMemory += size;
}
public static void _freeGPUMemory(long size) {
gpuMemory -= size;
}
public static long getCPUMemory() {
return cpuMemory;
}
public static long getGPUMemory() {
return gpuMemory;
}
}

View file

@ -0,0 +1,45 @@
package com.jozufozu.flywheel.backend.memory;
import java.nio.ByteBuffer;
public sealed interface MemoryBlock permits MemoryBlockImpl {
long ptr();
long size();
boolean isFreed();
boolean isTracked();
void copyTo(long ptr, long bytes);
default void copyTo(long ptr) {
copyTo(ptr, size());
}
void clear();
ByteBuffer asBuffer();
MemoryBlock realloc(long size);
MemoryBlock reallocTracked(long size);
void free();
static MemoryBlock malloc(long size) {
return FlwMemoryTracker.mallocBlock(size);
}
static MemoryBlock calloc(long num, long size) {
return FlwMemoryTracker.callocBlock(num, size);
}
static MemoryBlock mallocTracked(long size) {
return FlwMemoryTracker.mallocBlockTracked(size);
}
static MemoryBlock callocTracked(long num, long size) {
return FlwMemoryTracker.callocBlockTracked(num, size);
}
}

View file

@ -0,0 +1,76 @@
package com.jozufozu.flywheel.backend.memory;
import java.nio.ByteBuffer;
import org.lwjgl.system.MemoryUtil;
sealed class MemoryBlockImpl implements MemoryBlock permits TrackedMemoryBlockImpl {
final long ptr;
final long size;
boolean freed;
MemoryBlockImpl(long ptr, long size) {
this.ptr = ptr;
this.size = size;
}
@Override
public long ptr() {
return ptr;
}
@Override
public long size() {
return size;
}
@Override
public boolean isFreed() {
return freed;
}
@Override
public boolean isTracked() {
return false;
}
@Override
public void copyTo(long ptr, long bytes) {
MemoryUtil.memCopy(this.ptr, ptr, bytes);
}
@Override
public void clear() {
MemoryUtil.memSet(ptr, 0, size);
}
@Override
public ByteBuffer asBuffer() {
int intSize = (int) size;
if (intSize != size) {
throw new UnsupportedOperationException("Cannot create buffer with long capacity!");
}
return MemoryUtil.memByteBuffer(ptr, intSize);
}
@Override
public MemoryBlock realloc(long size) {
MemoryBlock block = FlwMemoryTracker.reallocBlock(this, size);
freed = true;
return block;
}
@Override
public MemoryBlock reallocTracked(long size) {
MemoryBlock block = FlwMemoryTracker.reallocBlockTracked(this, size);
freed = true;
return block;
}
@Override
public void free() {
FlwMemoryTracker.freeBlock(this);
freed = true;
}
}

View file

@ -0,0 +1,38 @@
package com.jozufozu.flywheel.backend.memory;
import java.lang.ref.Cleaner;
final class TrackedMemoryBlockImpl extends MemoryBlockImpl {
Cleaner.Cleanable cleanable;
TrackedMemoryBlockImpl(long ptr, long size) {
super(ptr, size);
}
@Override
public boolean isTracked() {
return true;
}
@Override
public MemoryBlock realloc(long size) {
MemoryBlock block = FlwMemoryTracker.reallocBlock(this, size);
freed = true;
cleanable.clean();
return block;
}
@Override
public MemoryBlock reallocTracked(long size) {
MemoryBlock block = FlwMemoryTracker.reallocBlockTracked(this, size);
freed = true;
cleanable.clean();
return block;
}
@Override
public void free() {
cleanable.clean();
freed = true;
}
}

View file

@ -1,40 +0,0 @@
package com.jozufozu.flywheel.backend.struct;
import java.nio.ByteBuffer;
import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.struct.StructWriter;
public abstract class BufferWriter<S extends InstancedPart> implements StructWriter<S> {
protected final ByteBuffer backingBuffer;
protected final int stride;
protected BufferWriter(StructType<S> structType, ByteBuffer byteBuffer) {
this.backingBuffer = byteBuffer;
this.stride = structType.getLayout().getStride();
}
@Override
public final void write(S struct) {
writeInternal(struct);
advance();
}
/**
* Advances the write pointer forward by the stride of one vertex.
* This will always be called after a struct is written, implementors need not call it themselves.
*
* @see #write
*/
protected abstract void advance();
protected abstract void writeInternal(S s);
@Override
public void seek(int pos) {
backingBuffer.position(pos * stride);
}
}

View file

@ -1,45 +0,0 @@
package com.jozufozu.flywheel.backend.struct;
import java.nio.ByteBuffer;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.instancer.InstancedPart;
import com.jozufozu.flywheel.api.struct.StructType;
/**
* This class copied/adapted from jellysquid's
*
* An unsafe {@link BufferWriter} implementation which uses direct memory operations to enable fast blitting of
* data into memory buffers. Only available on JVMs which support {@link sun.misc.Unsafe}, but generally produces much
* better optimized code than other implementations. The implementation does not check for invalid memory accesses,
* meaning that errors can corrupt process memory.
*/
public abstract class UnsafeBufferWriter<S extends InstancedPart> extends BufferWriter<S> {
/**
* The write pointer into the buffer storage. This is advanced by the stride every time
* {@link UnsafeBufferWriter#advance()} is called.
*/
protected long writePointer;
protected UnsafeBufferWriter(StructType<S> structType, ByteBuffer byteBuffer) {
super(structType, byteBuffer);
acquireWritePointer();
}
@Override
public void seek(int pos) {
super.seek(pos);
acquireWritePointer();
}
@Override
protected void advance() {
this.writePointer += this.stride;
}
private void acquireWritePointer() {
this.writePointer = MemoryUtil.memAddress(this.backingBuffer, this.backingBuffer.position());
}
}

View file

@ -1,6 +0,0 @@
@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
package com.jozufozu.flywheel.backend.struct;
import javax.annotation.ParametersAreNonnullByDefault;
import net.minecraft.MethodsReturnNonnullByDefault;

View file

@ -1,20 +1,17 @@
package com.jozufozu.flywheel.core.hardcoded;
import java.nio.ByteBuffer;
import java.util.List;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
import com.jozufozu.flywheel.backend.memory.MemoryBlock;
import com.jozufozu.flywheel.core.model.Mesh;
import com.jozufozu.flywheel.core.vertex.Formats;
import com.jozufozu.flywheel.core.vertex.PosTexNormalVertex;
import com.mojang.blaze3d.platform.MemoryTracker;
public class ModelPart implements Mesh {
private final int vertexCount;
private final ByteBuffer contents;
private final MemoryBlock contents;
private final ReusableVertexList vertexList;
private final String name;
@ -29,8 +26,8 @@ public class ModelPart implements Mesh {
this.vertexCount = vertices;
}
contents = MemoryTracker.create(size());
long ptr = MemoryUtil.memAddress(contents);
contents = MemoryBlock.malloc(size());
long ptr = contents.ptr();
VertexWriter writer = new VertexWriterImpl(ptr);
for (PartBuilder.CuboidBuilder cuboid : cuboids) {
cuboid.write(writer);
@ -56,19 +53,18 @@ public class ModelPart implements Mesh {
}
@Override
public void writeInto(ByteBuffer buffer, long byteIndex) {
buffer.position((int) byteIndex);
MemoryUtil.memCopy(contents, buffer);
public void write(long ptr) {
contents.copyTo(ptr);
}
@Override
public void writeInto(MutableVertexList dst) {
public void write(MutableVertexList dst) {
vertexList.writeAll(dst);
}
@Override
public void close() {
MemoryUtil.memFree(contents);
contents.free();
}
@Override

View file

@ -1,7 +1,5 @@
package com.jozufozu.flywheel.core.model;
import java.nio.ByteBuffer;
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.backend.instancing.instancing.ElementBuffer;
@ -51,9 +49,9 @@ public interface Mesh {
return getVertexType().byteOffset(getVertexCount());
}
void writeInto(ByteBuffer buffer, long byteIndex);
void write(long ptr);
void writeInto(MutableVertexList vertexList);
void write(MutableVertexList vertexList);
/**
* Create an element buffer object that indexes the vertices of this mesh.

View file

@ -10,10 +10,10 @@ import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.backend.memory.MemoryBlock;
import com.jozufozu.flywheel.core.Materials;
import com.jozufozu.flywheel.core.vertex.Formats;
import com.jozufozu.flywheel.core.vertex.VertexListProviderRegistry;
import com.mojang.blaze3d.platform.MemoryTracker;
import com.mojang.blaze3d.vertex.BufferBuilder.DrawState;
import com.mojang.blaze3d.vertex.VertexFormat;
import com.mojang.datafixers.util.Pair;
@ -47,16 +47,16 @@ public class ModelUtil {
return dispatcher;
}
public static Pair<VertexType, ByteBuffer> convertBlockBuffer(Pair<DrawState, ByteBuffer> pair) {
public static Pair<VertexType, MemoryBlock> convertBlockBuffer(Pair<DrawState, ByteBuffer> pair) {
DrawState drawState = pair.getFirst();
int vertexCount = drawState.vertexCount();
VertexFormat srcFormat = drawState.format();
VertexType dstVertexType = Formats.BLOCK;
ByteBuffer src = pair.getSecond();
ByteBuffer dst = MemoryTracker.create(src.capacity());
MemoryBlock dst = MemoryBlock.malloc(src.capacity());
long srcPtr = MemoryUtil.memAddress(src);
long dstPtr = MemoryUtil.memAddress(dst);
long dstPtr = dst.ptr();
ReusableVertexList srcList = VertexListProviderRegistry.getOrInfer(srcFormat).createVertexList();
ReusableVertexList dstList = dstVertexType.createVertexList();

View file

@ -1,35 +1,31 @@
package com.jozufozu.flywheel.core.model;
import java.nio.ByteBuffer;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.backend.memory.MemoryBlock;
public class SimpleMesh implements Mesh {
private final VertexType vertexType;
private final int vertexCount;
private final ByteBuffer contents;
private final MemoryBlock contents;
private final ReusableVertexList vertexList;
private final String name;
public SimpleMesh(VertexType vertexType, ByteBuffer contents, String name) {
public SimpleMesh(VertexType vertexType, MemoryBlock contents, String name) {
this.vertexType = vertexType;
this.contents = contents;
this.name = name;
contents.clear();
int bytes = contents.remaining();
int bytes = (int) contents.size();
int stride = vertexType.getStride();
if (bytes % stride != 0) {
throw new IllegalArgumentException("Buffer contains non-whole amount of vertices!");
throw new IllegalArgumentException("MemoryBlock contains non-whole amount of vertices!");
}
vertexCount = bytes / stride;
vertexList = getVertexType().createVertexList();
vertexList.ptr(MemoryUtil.memAddress(contents));
vertexList.ptr(contents.ptr());
vertexList.setVertexCount(vertexCount);
}
@ -44,19 +40,18 @@ public class SimpleMesh implements Mesh {
}
@Override
public void writeInto(ByteBuffer buffer, long byteIndex) {
buffer.position((int) byteIndex);
MemoryUtil.memCopy(contents, buffer);
public void write(long ptr) {
contents.copyTo(ptr);
}
@Override
public void writeInto(MutableVertexList dst) {
public void write(MutableVertexList dst) {
vertexList.writeAll(dst);
}
@Override
public void close() {
MemoryUtil.memFree(contents);
contents.free();
}
@Override

View file

@ -1,11 +1,11 @@
package com.jozufozu.flywheel.core.model.buffering;
import java.nio.ByteBuffer;
import java.util.function.BiFunction;
import com.google.common.collect.ImmutableMap;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.backend.memory.MemoryBlock;
import com.jozufozu.flywheel.core.model.Mesh;
import com.jozufozu.flywheel.core.model.ModelUtil;
import com.jozufozu.flywheel.core.model.SimpleMesh;
@ -104,7 +104,7 @@ public class BakedModelBuilder {
buffer.end();
Material material = materialFunc.apply(renderType, shaded);
if (material != null) {
Pair<VertexType, ByteBuffer> pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer());
Pair<VertexType, MemoryBlock> pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer());
meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "bakedModel=" + bakedModel.toString() + ",renderType=" + renderType.toString() + ",shaded=" + shaded));
}
};
@ -119,7 +119,7 @@ public class BakedModelBuilder {
buffer.end();
Material material = materialFunc.apply(renderType, false);
if (material != null) {
Pair<VertexType, ByteBuffer> pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer());
Pair<VertexType, MemoryBlock> pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer());
meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "bakedModel=" + bakedModel.toString() + ",renderType=" + renderType.toString()));
}
};

View file

@ -1,11 +1,11 @@
package com.jozufozu.flywheel.core.model.buffering;
import java.nio.ByteBuffer;
import java.util.function.BiFunction;
import com.google.common.collect.ImmutableMap;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.backend.memory.MemoryBlock;
import com.jozufozu.flywheel.core.model.Mesh;
import com.jozufozu.flywheel.core.model.ModelUtil;
import com.jozufozu.flywheel.core.model.SimpleMesh;
@ -93,7 +93,7 @@ public class BlockModelBuilder {
buffer.end();
Material material = materialFunc.apply(renderType, shaded);
if (material != null) {
Pair<VertexType, ByteBuffer> pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer());
Pair<VertexType, MemoryBlock> pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer());
meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "state=" + state.toString() + ",renderType=" + renderType.toString() + ",shaded=" + shaded));
}
};
@ -108,7 +108,7 @@ public class BlockModelBuilder {
buffer.end();
Material material = materialFunc.apply(renderType, false);
if (material != null) {
Pair<VertexType, ByteBuffer> pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer());
Pair<VertexType, MemoryBlock> pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer());
meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "state=" + state.toString() + ",renderType=" + renderType.toString()));
}
};

View file

@ -1,6 +1,5 @@
package com.jozufozu.flywheel.core.model.buffering;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
@ -9,6 +8,7 @@ import java.util.function.BiFunction;
import com.google.common.collect.ImmutableMap;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.backend.memory.MemoryBlock;
import com.jozufozu.flywheel.core.model.Mesh;
import com.jozufozu.flywheel.core.model.ModelUtil;
import com.jozufozu.flywheel.core.model.SimpleMesh;
@ -100,7 +100,7 @@ public class MultiBlockModelBuilder {
buffer.end();
Material material = materialFunc.apply(renderType, shaded);
if (material != null) {
Pair<VertexType, ByteBuffer> pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer());
Pair<VertexType, MemoryBlock> pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer());
meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "renderType=" + renderType.toString() + ",shaded=" + shaded));
}
};
@ -115,7 +115,7 @@ public class MultiBlockModelBuilder {
buffer.end();
Material material = materialFunc.apply(renderType, false);
if (material != null) {
Pair<VertexType, ByteBuffer> pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer());
Pair<VertexType, MemoryBlock> pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer());
meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "renderType=" + renderType.toString()));
}
};

View file

@ -0,0 +1,17 @@
package com.jozufozu.flywheel.core.structs;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.struct.StructWriter;
public abstract class ColoredLitWriter<D extends ColoredLitPart> implements StructWriter<D> {
@Override
public void write(long ptr, D d) {
MemoryUtil.memPutByte(ptr, d.blockLight);
MemoryUtil.memPutByte(ptr + 1, d.skyLight);
MemoryUtil.memPutByte(ptr + 2, d.r);
MemoryUtil.memPutByte(ptr + 3, d.g);
MemoryUtil.memPutByte(ptr + 4, d.b);
MemoryUtil.memPutByte(ptr + 5, d.a);
}
}

View file

@ -1,26 +0,0 @@
package com.jozufozu.flywheel.core.structs;
import java.nio.ByteBuffer;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.backend.struct.UnsafeBufferWriter;
public abstract class ColoredLitWriterUnsafe<D extends ColoredLitPart> extends UnsafeBufferWriter<D> {
public ColoredLitWriterUnsafe(StructType<D> structType, ByteBuffer byteBuffer) {
super(structType, byteBuffer);
}
@Override
protected void writeInternal(D d) {
long ptr = writePointer;
MemoryUtil.memPutByte(ptr, d.blockLight);
MemoryUtil.memPutByte(ptr + 1, d.skyLight);
MemoryUtil.memPutByte(ptr + 2, d.r);
MemoryUtil.memPutByte(ptr + 3, d.g);
MemoryUtil.memPutByte(ptr + 4, d.b);
MemoryUtil.memPutByte(ptr + 5, d.a);
}
}

View file

@ -2,10 +2,10 @@ package com.jozufozu.flywheel.core.structs;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.core.ComponentRegistry;
import com.jozufozu.flywheel.core.structs.model.TransformedPart;
import com.jozufozu.flywheel.core.structs.model.TransformedType;
import com.jozufozu.flywheel.core.structs.oriented.OrientedPart;
import com.jozufozu.flywheel.core.structs.oriented.OrientedType;
import com.jozufozu.flywheel.core.structs.transformed.TransformedPart;
import com.jozufozu.flywheel.core.structs.transformed.TransformedType;
public class StructTypes {
public static final StructType<TransformedPart> TRANSFORMED = ComponentRegistry.register(new TransformedType());

View file

@ -1,23 +0,0 @@
package com.jozufozu.flywheel.core.structs.model;
import java.nio.ByteBuffer;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.core.structs.ColoredLitWriterUnsafe;
import com.jozufozu.flywheel.util.MatrixWrite;
public class TransformedWriterUnsafe extends ColoredLitWriterUnsafe<TransformedPart> {
public TransformedWriterUnsafe(StructType<TransformedPart> structType, ByteBuffer byteBuffer) {
super(structType, byteBuffer);
}
@Override
protected void writeInternal(TransformedPart d) {
super.writeInternal(d);
long ptr = writePointer + 6;
((MatrixWrite) (Object) d.model).flywheel$writeUnsafe(ptr);
((MatrixWrite) (Object) d.normal).flywheel$writeUnsafe(ptr + 4 * 16);
}
}

View file

@ -1,7 +1,5 @@
package com.jozufozu.flywheel.core.structs.oriented;
import java.nio.ByteBuffer;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.struct.StructWriter;
import com.jozufozu.flywheel.core.Components;
@ -32,8 +30,8 @@ public class OrientedType implements StructType<OrientedPart> {
}
@Override
public StructWriter<OrientedPart> getWriter(ByteBuffer backing) {
return new OrientedWriterUnsafe(this, backing);
public StructWriter<OrientedPart> getWriter() {
return OrientedWriter.INSTANCE;
}
@Override
@ -42,7 +40,7 @@ public class OrientedType implements StructType<OrientedPart> {
}
@Override
public VertexTransformer<? extends OrientedPart> getVertexTransformer() {
public VertexTransformer<OrientedPart> getVertexTransformer() {
return (vertexList, struct, level) -> {
Vector4f pos = new Vector4f();
Vector3f normal = new Vector3f();

View file

@ -1,21 +1,15 @@
package com.jozufozu.flywheel.core.structs.oriented;
import java.nio.ByteBuffer;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.core.structs.ColoredLitWriterUnsafe;
import com.jozufozu.flywheel.core.structs.ColoredLitWriter;
public class OrientedWriterUnsafe extends ColoredLitWriterUnsafe<OrientedPart> {
public OrientedWriterUnsafe(StructType<OrientedPart> structType, ByteBuffer byteBuffer) {
super(structType, byteBuffer);
}
public class OrientedWriter extends ColoredLitWriter<OrientedPart> {
public static final OrientedWriter INSTANCE = new OrientedWriter();
@Override
protected void writeInternal(OrientedPart d) {
long ptr = writePointer;
super.writeInternal(d);
public void write(long ptr, OrientedPart d) {
super.write(ptr, d);
MemoryUtil.memPutFloat(ptr + 6, d.posX);
MemoryUtil.memPutFloat(ptr + 10, d.posY);

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.core.structs.model;
package com.jozufozu.flywheel.core.structs.transformed;
import com.jozufozu.flywheel.core.structs.ColoredLitPart;
import com.jozufozu.flywheel.core.structs.StructTypes;

View file

@ -1,6 +1,4 @@
package com.jozufozu.flywheel.core.structs.model;
import java.nio.ByteBuffer;
package com.jozufozu.flywheel.core.structs.transformed;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.struct.StructWriter;
@ -29,8 +27,8 @@ public class TransformedType implements StructType<TransformedPart> {
}
@Override
public StructWriter<TransformedPart> getWriter(ByteBuffer backing) {
return new TransformedWriterUnsafe(this, backing);
public StructWriter<TransformedPart> getWriter() {
return TransformedWriter.INSTANCE;
}
@Override
@ -39,7 +37,7 @@ public class TransformedType implements StructType<TransformedPart> {
}
@Override
public VertexTransformer<? extends TransformedPart> getVertexTransformer() {
public VertexTransformer<TransformedPart> getVertexTransformer() {
return (vertexList, struct, level) -> {
Vector4f pos = new Vector4f();
Vector3f normal = new Vector3f();

View file

@ -0,0 +1,17 @@
package com.jozufozu.flywheel.core.structs.transformed;
import com.jozufozu.flywheel.core.structs.ColoredLitWriter;
import com.jozufozu.flywheel.util.MatrixWrite;
public class TransformedWriter extends ColoredLitWriter<TransformedPart> {
public static final TransformedWriter INSTANCE = new TransformedWriter();
@Override
public void write(long ptr, TransformedPart d) {
super.write(ptr, d);
ptr += 6;
((MatrixWrite) (Object) d.model).flywheel$writeUnsafe(ptr);
((MatrixWrite) (Object) d.normal).flywheel$writeUnsafe(ptr + 4 * 16);
}
}

View file

@ -1,5 +1,5 @@
@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
package com.jozufozu.flywheel.core.structs.model;
package com.jozufozu.flywheel.core.structs.transformed;
import javax.annotation.ParametersAreNonnullByDefault;

View file

@ -9,8 +9,6 @@ import com.mojang.blaze3d.systems.RenderSystem;
public class FogProvider extends UniformProvider {
@Override
public int getSize() {
return 16 + 8 + 4;

View file

@ -12,9 +12,9 @@ import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.api.uniform.UniformProvider;
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
import com.jozufozu.flywheel.backend.memory.FlwMemoryTracker;
import com.jozufozu.flywheel.core.ComponentRegistry;
import com.jozufozu.flywheel.util.RenderMath;
import com.mojang.blaze3d.platform.MemoryTracker;
public class UniformBuffer {
@ -57,7 +57,7 @@ public class UniformBuffer {
allocatedProviders = builder.build();
data = MemoryTracker.create(totalBytes);
data = FlwMemoryTracker.mallocBuffer(totalBytes);
changedBytes = new BitSet(totalBytes);
for (Allocated p : allocatedProviders) {

View file

@ -4,8 +4,8 @@ import java.util.ArrayList;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.FlywheelMemory;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.backend.memory.FlwMemoryTracker;
import com.jozufozu.flywheel.light.LightUpdater;
import com.jozufozu.flywheel.util.WorldAttached;
@ -24,10 +24,7 @@ public class ForgeEvents {
InstancedRenderDispatcher.getDebugString(debug);
// TODO: compress into one line
debug.add("Memory used:");
debug.add("GPU: " + FlywheelMemory.getGPUMemory());
debug.add("CPU: " + FlywheelMemory.getCPUMemory());
debug.add("Memory Usage: CPU: " + FlwMemoryTracker.getCPUMemory() / 1024 + "KiB GPU: " + FlwMemoryTracker.getGPUMemory() / 1024 + "KiB");
}
}

View file

@ -2,8 +2,7 @@ package com.jozufozu.flywheel.light;
import java.nio.ByteBuffer;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.backend.memory.FlwMemoryTracker;
import com.jozufozu.flywheel.util.box.GridAlignedBB;
import com.jozufozu.flywheel.util.box.ImmutableBox;
@ -21,7 +20,7 @@ public class LightVolume implements ImmutableBox, LightListener {
this.level = level;
this.setBox(sampleVolume);
this.lightData = MemoryUtil.memAlloc(this.box.volume() * 2);
this.lightData = FlwMemoryTracker.mallocBuffer(this.box.volume() * 2);
}
protected void setBox(ImmutableBox box) {
@ -66,7 +65,7 @@ public class LightVolume implements ImmutableBox, LightListener {
setBox(newSampleVolume);
int neededCapacity = box.volume() * 2;
if (neededCapacity > lightData.capacity()) {
lightData = MemoryUtil.memRealloc(lightData, neededCapacity);
lightData = FlwMemoryTracker.reallocBuffer(lightData, neededCapacity);
}
initialize();
}
@ -168,7 +167,7 @@ public class LightVolume implements ImmutableBox, LightListener {
}
public void delete() {
MemoryUtil.memFree(lightData);
FlwMemoryTracker.freeBuffer(lightData);
lightData = null;
}

View file

@ -15,6 +15,8 @@ import java.util.stream.Collectors;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.backend.memory.FlwMemoryTracker;
public class StringUtil {
private static final NumberFormat timeFormat = new DecimalFormat("#0.000");
@ -56,11 +58,11 @@ public class StringUtil {
((Buffer) bytebuffer).rewind();
return MemoryUtil.memASCII(bytebuffer, i);
} catch (IOException ignored) {
//
} finally {
if (bytebuffer != null) {
MemoryUtil.memFree(bytebuffer);
FlwMemoryTracker.freeBuffer(bytebuffer);
}
}
return null;
@ -75,12 +77,12 @@ public class StringUtil {
}
private static ByteBuffer readInputStream(InputStream is) throws IOException {
ByteBuffer bytebuffer = MemoryUtil.memAlloc(8192);
ByteBuffer bytebuffer = FlwMemoryTracker.mallocBuffer(8192);
ReadableByteChannel readablebytechannel = Channels.newChannel(is);
while (readablebytechannel.read(bytebuffer) != -1) {
if (bytebuffer.remaining() == 0) {
bytebuffer = MemoryUtil.memRealloc(bytebuffer, bytebuffer.capacity() * 2);
bytebuffer = FlwMemoryTracker.reallocBuffer(bytebuffer, bytebuffer.capacity() * 2);
}
}
return bytebuffer;
@ -88,7 +90,7 @@ public class StringUtil {
private static ByteBuffer readFileInputStream(FileInputStream fileinputstream) throws IOException {
FileChannel filechannel = fileinputstream.getChannel();
ByteBuffer bytebuffer = MemoryUtil.memAlloc((int) filechannel.size() + 1);
ByteBuffer bytebuffer = FlwMemoryTracker.mallocBuffer((int) filechannel.size() + 1);
while (filechannel.read(bytebuffer) != -1) {
}

View file

@ -15,8 +15,8 @@ import com.jozufozu.flywheel.core.Materials;
import com.jozufozu.flywheel.core.hardcoded.ModelPart;
import com.jozufozu.flywheel.core.model.SimpleLazyModel;
import com.jozufozu.flywheel.core.structs.StructTypes;
import com.jozufozu.flywheel.core.structs.model.TransformedPart;
import com.jozufozu.flywheel.core.structs.oriented.OrientedPart;
import com.jozufozu.flywheel.core.structs.transformed.TransformedPart;
import com.jozufozu.flywheel.util.AnimationTickHolder;
import com.mojang.math.Quaternion;
import com.mojang.math.Vector3f;

View file

@ -12,7 +12,7 @@ import com.jozufozu.flywheel.core.model.Mesh;
import com.jozufozu.flywheel.core.model.Models;
import com.jozufozu.flywheel.core.model.SimpleLazyModel;
import com.jozufozu.flywheel.core.structs.StructTypes;
import com.jozufozu.flywheel.core.structs.model.TransformedPart;
import com.jozufozu.flywheel.core.structs.transformed.TransformedPart;
import com.jozufozu.flywheel.util.AnimationTickHolder;
import com.jozufozu.flywheel.util.transform.TransformStack;
import com.mojang.blaze3d.vertex.PoseStack;

View file

@ -12,7 +12,7 @@ import com.jozufozu.flywheel.core.Materials;
import com.jozufozu.flywheel.core.hardcoded.ModelPart;
import com.jozufozu.flywheel.core.model.SimpleLazyModel;
import com.jozufozu.flywheel.core.structs.StructTypes;
import com.jozufozu.flywheel.core.structs.model.TransformedPart;
import com.jozufozu.flywheel.core.structs.transformed.TransformedPart;
import com.jozufozu.flywheel.util.AnimationTickHolder;
import com.jozufozu.flywheel.util.transform.TransformStack;
import com.mojang.blaze3d.vertex.PoseStack;

View file

@ -13,7 +13,7 @@ import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.backend.instancing.effect.Effect;
import com.jozufozu.flywheel.core.model.Models;
import com.jozufozu.flywheel.core.structs.StructTypes;
import com.jozufozu.flywheel.core.structs.model.TransformedPart;
import com.jozufozu.flywheel.core.structs.transformed.TransformedPart;
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
import com.jozufozu.flywheel.util.AnimationTickHolder;
import com.jozufozu.flywheel.util.box.GridAlignedBB;