diff --git a/build.gradle b/build.gradle
index d65d4f49d..b8364464a 100644
--- a/build.gradle
+++ b/build.gradle
@@ -43,6 +43,7 @@ minecraft {
property 'forge.logging.markers', ''
property 'forge.logging.console.level', 'debug'
property 'mixin.debug.export', 'true'
+ property 'flw.dumpShaderSource', 'true'
arg '-mixin.config=flywheel.mixins.json'
diff --git a/src/main/java/com/jozufozu/flywheel/api/struct/InstancedStructType.java b/src/main/java/com/jozufozu/flywheel/api/struct/InstancedStructType.java
index 3a6ac7440..1a809163a 100644
--- a/src/main/java/com/jozufozu/flywheel/api/struct/InstancedStructType.java
+++ b/src/main/java/com/jozufozu/flywheel/api/struct/InstancedStructType.java
@@ -1,6 +1,7 @@
package com.jozufozu.flywheel.api.struct;
-import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
+import java.nio.ByteBuffer;
+
import com.jozufozu.flywheel.core.source.FileResolution;
public interface InstancedStructType extends StructType {
@@ -9,7 +10,7 @@ public interface InstancedStructType extends StructType {
*
* @param backing The buffer that the StructWriter will write to.
*/
- StructWriter getWriter(VecBuffer backing);
+ StructWriter getWriter(ByteBuffer backing);
FileResolution getInstanceShader();
}
diff --git a/src/main/java/com/jozufozu/flywheel/backend/Backend.java b/src/main/java/com/jozufozu/flywheel/backend/Backend.java
index 79f4b6c93..aaf2e4e51 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/Backend.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/Backend.java
@@ -1,5 +1,7 @@
package com.jozufozu.flywheel.backend;
+import java.lang.ref.Cleaner;
+
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
@@ -17,6 +19,8 @@ import net.minecraft.world.level.LevelAccessor;
public class Backend {
public static final Logger LOGGER = LogUtils.getLogger();
+ public static boolean dumpShaderSource = Boolean.getBoolean("flw.dumpShaderSource");
+
private static BackendType backendType;
private static ParallelTaskEngine taskEngine;
@@ -105,4 +109,5 @@ public class Backend {
private Backend() {
throw new UnsupportedOperationException("Backend is a static class!");
}
+
}
diff --git a/src/main/java/com/jozufozu/flywheel/backend/FlywheelDebug.java b/src/main/java/com/jozufozu/flywheel/backend/FlywheelDebug.java
new file mode 100644
index 000000000..48caf3cb9
--- /dev/null
+++ b/src/main/java/com/jozufozu/flywheel/backend/FlywheelDebug.java
@@ -0,0 +1,32 @@
+package com.jozufozu.flywheel.backend;
+
+import org.lwjgl.opengl.GL43;
+import org.lwjgl.opengl.GLDebugMessageCallback;
+
+import com.mojang.blaze3d.platform.GlDebug;
+
+public class FlywheelDebug {
+//
+// public static void setup() {
+// GLDebugMessageCallback.create()
+// GL43.glDebugMessageCallback();
+// }
+//
+// private static void printDebugLog(int p_84039_, int p_84040_, int p_84041_, int p_84042_, int p_84043_, long p_84044_, long p_84045_) {
+// String s = GLDebugMessageCallback.getMessage(p_84043_, p_84044_);
+// GlDebug.LogEntry gldebug$logentry;
+// synchronized(MESSAGE_BUFFER) {
+// gldebug$logentry = lastEntry;
+// if (gldebug$logentry != null && gldebug$logentry.isSame(p_84039_, p_84040_, p_84041_, p_84042_, s)) {
+// ++gldebug$logentry.count;
+// } else {
+// gldebug$logentry = new GlDebug.LogEntry(p_84039_, p_84040_, p_84041_, p_84042_, s);
+// MESSAGE_BUFFER.add(gldebug$logentry);
+// lastEntry = gldebug$logentry;
+// }
+// }
+//
+// LOGGER.info("OpenGL debug message: {}", (Object)gldebug$logentry);
+// }
+
+}
diff --git a/src/main/java/com/jozufozu/flywheel/backend/FlywheelMemory.java b/src/main/java/com/jozufozu/flywheel/backend/FlywheelMemory.java
new file mode 100644
index 000000000..3d3f8bd60
--- /dev/null
+++ b/src/main/java/com/jozufozu/flywheel/backend/FlywheelMemory.java
@@ -0,0 +1,57 @@
+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);
+ }
+ }
+}
diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/GlObject.java b/src/main/java/com/jozufozu/flywheel/backend/gl/GlObject.java
index 27956c87e..48904d20c 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/gl/GlObject.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/gl/GlObject.java
@@ -1,5 +1,7 @@
package com.jozufozu.flywheel.backend.gl;
+import com.jozufozu.flywheel.backend.RenderWork;
+
// Utility class for safely dealing with gl object handles.
public abstract class GlObject {
private static final int INVALID_HANDLE = Integer.MIN_VALUE;
@@ -40,5 +42,4 @@ public abstract class GlObject {
}
protected abstract void deleteInternal(int handle);
-
}
diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/GlStateTracker.java b/src/main/java/com/jozufozu/flywheel/backend/gl/GlStateTracker.java
index eec0a4cf8..a352e9465 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/gl/GlStateTracker.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/gl/GlStateTracker.java
@@ -40,7 +40,7 @@ public class GlStateTracker {
return new State(buffers.clone(), vao, program);
}
- public static record State(int[] buffers, int vao, int program) {
+ public record State(int[] buffers, int vao, int program) implements AutoCloseable {
public void restore() {
GlBufferType[] values = GlBufferType.values();
@@ -58,5 +58,10 @@ public class GlStateTracker {
GlStateManager._glUseProgram(program);
}
}
+
+ @Override
+ public void close() {
+ restore();
+ }
}
}
diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/GlVertexArray.java b/src/main/java/com/jozufozu/flywheel/backend/gl/GlVertexArray.java
index f5f54047b..7de9ef863 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/gl/GlVertexArray.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/gl/GlVertexArray.java
@@ -3,6 +3,7 @@ package com.jozufozu.flywheel.backend.gl;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL32;
+import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
import com.jozufozu.flywheel.backend.gl.versioned.GlCompat;
import com.jozufozu.flywheel.core.layout.BufferLayout;
@@ -61,16 +62,19 @@ public class GlVertexArray extends GlObject {
GlStateManager._glBindVertexArray(0);
}
- public void bindAttributes(int startIndex, BufferLayout type) {
- int boundBuffer = GlStateTracker.getBuffer(GlBufferType.ARRAY_BUFFER);
-
+ public void bindAttributes(GlBuffer buffer, int startIndex, BufferLayout type) {
bind();
+
+ int targetBuffer = buffer.handle();
+
+ GlBufferType.ARRAY_BUFFER.bind(targetBuffer);
+
int i = startIndex;
int offset = 0;
final int stride = type.getStride();
for (VertexAttribute attribute : type.getAttributes()) {
- targets[i] = boundBuffer;
+ targets[i] = targetBuffer;
attributes[i] = attribute;
offsets[i] = offset;
strides[i] = stride;
diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/GlBuffer.java b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/GlBuffer.java
index 55d8d7037..09c186a9d 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/GlBuffer.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/GlBuffer.java
@@ -29,12 +29,12 @@ public abstract class GlBuffer extends GlObject {
}
}
- protected final GlBufferType type;
+ public final GlBufferType type;
/**
* The size (in bytes) of the buffer on the GPU.
*/
- protected long capacity;
+ protected long size;
/**
* How much extra room to give the buffer when we reallocate.
@@ -42,7 +42,7 @@ public abstract class GlBuffer extends GlObject {
protected int growthMargin;
public GlBuffer(GlBufferType type) {
- _create();
+ setHandle(GL20.glGenBuffers());
this.type = type;
}
@@ -50,42 +50,14 @@ public abstract class GlBuffer extends GlObject {
this.growthMargin = growthMargin;
}
- public long getCapacity() {
- return capacity;
+ public long getSize() {
+ return size;
}
- public MappedBuffer getBuffer() {
- return getBuffer(0, capacity);
+ public GlBufferType getType() {
+ return type;
}
- public abstract MappedBuffer getBuffer(long offset, long length);
-
- /**
- * Ensure that the buffer has at least enough room to store size bytes.
- *
- * @return true if the buffer grew.
- */
- public boolean ensureCapacity(long size) {
- if (size > capacity) {
- capacity = size + growthMargin;
- alloc(capacity);
- return true;
- }
-
- return false;
- }
-
- /**
- * Call this after all draw calls using this buffer are complete.
- */
- public void doneForThisFrame() {
-
- }
-
- protected abstract void alloc(long size);
-
- public abstract void upload(ByteBuffer directBuffer);
-
public void bind() {
type.bind(handle());
}
@@ -94,11 +66,31 @@ public abstract class GlBuffer extends GlObject {
type.unbind();
}
- protected void _create() {
- setHandle(GL20.glGenBuffers());
+ public abstract void upload(ByteBuffer directBuffer);
+
+ public abstract MappedBuffer map();
+
+ /**
+ * Ensure that the buffer has at least enough room to store {@code size} bytes.
+ *
+ * @return {@code true} if the buffer moved.
+ */
+ public abstract boolean ensureCapacity(long size);
+
+ /**
+ * Call this after all draw calls using this buffer are complete.
+ */
+ public void doneForThisFrame() {
+
}
protected void deleteInternal(int handle) {
GL20.glDeleteBuffers(handle);
}
+
+ /**
+ * Indicates that this buffer need not be #flush()'d for its contents to sync.
+ * @return true if this buffer is persistently mapped.
+ */
+ public abstract boolean isPersistent();
}
diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/GlBufferType.java b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/GlBufferType.java
index 776ed6328..91553e7ca 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/GlBufferType.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/GlBufferType.java
@@ -10,6 +10,7 @@ import org.lwjgl.opengl.GL43;
import com.jozufozu.flywheel.backend.gl.GlStateTracker;
import com.mojang.blaze3d.platform.GlStateManager;
+import com.mojang.blaze3d.systems.RenderSystem;
public enum GlBufferType {
ARRAY_BUFFER(GL15C.GL_ARRAY_BUFFER),
@@ -53,11 +54,13 @@ public enum GlBufferType {
}
public void bind(int buffer) {
- GlStateManager._glBindBuffer(glEnum, buffer);
+ if (getBoundBuffer() != buffer) {
+ GlStateManager._glBindBuffer(glEnum, buffer);
+ }
}
public void unbind() {
- GlStateManager._glBindBuffer(glEnum, 0);
+ bind(0);
}
public int getBoundBuffer() {
diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/Mappable.java b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/Mappable.java
deleted file mode 100644
index 8c5cddc42..000000000
--- a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/Mappable.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.jozufozu.flywheel.backend.gl.buffer;
-
-/**
- * Interface for generically dealing with mapped buffers.
- */
-public interface Mappable {
- GlBufferType getType();
-
- /**
- * Indicates that this buffer need not be #flush()'d for its contents to sync.
- * @return true if this buffer is persistently mapped.
- */
- boolean isPersistent();
-}
diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/MappedBuffer.java b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/MappedBuffer.java
index 25155a1d0..4ccdbe721 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/MappedBuffer.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/MappedBuffer.java
@@ -3,43 +3,69 @@ package com.jozufozu.flywheel.backend.gl.buffer;
import java.nio.ByteBuffer;
import org.lwjgl.opengl.GL15;
+import org.lwjgl.system.MemoryUtil;
-public class MappedBuffer extends VecBuffer implements AutoCloseable {
+public class MappedBuffer implements AutoCloseable {
- protected final long offset;
- protected final long length;
- protected final Mappable owner;
+ private final long offset;
+ private final long length;
+ private final GlBuffer owner;
+ private final boolean persistent;
+ private ByteBuffer internal;
- public MappedBuffer(Mappable owner, ByteBuffer internal, long offset, long length) {
+ public MappedBuffer(GlBuffer owner, ByteBuffer internal, long offset, long length) {
this.internal = internal;
this.owner = owner;
this.offset = offset;
this.length = length;
+ persistent = owner.isPersistent();
}
/**
* Make the changes in client memory available to the GPU.
*/
public void flush() {
- if (owner.isPersistent()) return;
+ if (persistent) return;
if (internal == null) return;
+ owner.bind();
GL15.glUnmapBuffer(owner.getType().glEnum);
internal = null;
}
- @Override
public MappedBuffer position(int p) {
if (p < offset || p >= offset + length) {
throw new IndexOutOfBoundsException("Index " + p + " is not mapped");
}
- super.position(p - (int) offset);
+ internal.position(p - (int) offset);
return this;
}
@Override
- public void close() throws Exception {
+ public void close() {
flush();
}
+
+ public ByteBuffer unwrap() {
+ return internal;
+ }
+
+ public long getMemAddress() {
+ return MemoryUtil.memAddress(internal);
+ }
+
+ public void clear(long clearStart, long clearLength) {
+ if (clearLength <= 0) {
+ return;
+ }
+
+ if (clearStart < offset || clearStart + clearLength > offset + length) {
+ throw new IndexOutOfBoundsException("Clear range [" + clearStart + "," + (clearStart + clearLength) + "] is not mapped");
+ }
+
+ long addr = MemoryUtil.memAddress(unwrap()) + clearStart;
+
+ MemoryUtil.memSet(addr, 0, clearLength);
+ }
}
diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/MappedGlBuffer.java b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/MappedGlBuffer.java
index aef6e8ce5..6d0e5956b 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/MappedGlBuffer.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/MappedGlBuffer.java
@@ -2,13 +2,13 @@ package com.jozufozu.flywheel.backend.gl.buffer;
import java.nio.ByteBuffer;
-import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL30;
+import org.lwjgl.opengl.GL32;
import com.jozufozu.flywheel.backend.gl.error.GlError;
import com.jozufozu.flywheel.backend.gl.error.GlException;
-public class MappedGlBuffer extends GlBuffer implements Mappable {
+public class MappedGlBuffer extends GlBuffer {
protected final GlBufferUsage usage;
@@ -21,27 +21,67 @@ public class MappedGlBuffer extends GlBuffer implements Mappable {
this.usage = usage;
}
- protected void alloc(long size) {
- GL15.glBufferData(type.glEnum, size, usage.glEnum);
+ @Override
+ public boolean ensureCapacity(long size) {
+ if (size < 0) {
+ throw new IllegalArgumentException("Size " + size + " < 0");
+ }
+
+ if (size == 0) {
+ return false;
+ }
+
+ if (this.size == 0) {
+ this.size = size;
+ bind();
+ GL32.glBufferData(type.glEnum, size, usage.glEnum);
+
+ return true;
+ }
+
+ if (size > this.size) {
+ var oldSize = this.size;
+ this.size = size + growthMargin;
+
+ realloc(oldSize, this.size);
+
+ return true;
+ }
+
+ return false;
}
+ private void realloc(long oldSize, long newSize) {
+ var oldHandle = handle();
+ var newHandle = GL32.glGenBuffers();
+
+ GlBufferType.COPY_READ_BUFFER.bind(oldHandle);
+ type.bind(newHandle);
+
+ GL32.glBufferData(type.glEnum, newSize, usage.glEnum);
+ GL32.glCopyBufferSubData(GlBufferType.COPY_READ_BUFFER.glEnum, type.glEnum, 0, 0, oldSize);
+
+ delete();
+ setHandle(newHandle);
+ }
+
+ @Override
public void upload(ByteBuffer directBuffer) {
- GL15.glBufferData(type.glEnum, directBuffer, usage.glEnum);
+ bind();
+ GL32.glBufferData(type.glEnum, directBuffer, usage.glEnum);
+ this.size = directBuffer.capacity();
}
- public MappedBuffer getBuffer(long offset, long length) {
- ByteBuffer byteBuffer = GL30.glMapBufferRange(type.glEnum, offset, length, GL30.GL_MAP_WRITE_BIT);
+ @Override
+ public MappedBuffer map() {
+ bind();
+ ByteBuffer byteBuffer = GL30.glMapBufferRange(type.glEnum, 0, size, GL30.GL_MAP_WRITE_BIT);
if (byteBuffer == null) {
throw new GlException(GlError.poll(), "Could not map buffer");
}
- return new MappedBuffer(this, byteBuffer, offset, length);
- }
-
- @Override
- public GlBufferType getType() {
- return type;
+ return new MappedBuffer(this, byteBuffer, 0, size);
}
@Override
diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/PersistentGlBuffer.java b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/PersistentGlBuffer.java
index ff81679c2..bf9293be6 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/PersistentGlBuffer.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/PersistentGlBuffer.java
@@ -6,20 +6,21 @@ import static org.lwjgl.opengl.GL44.GL_MAP_PERSISTENT_BIT;
import java.nio.ByteBuffer;
-import org.lwjgl.opengl.GL30;
+import org.jetbrains.annotations.Nullable;
+import org.lwjgl.opengl.GL32;
+import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.backend.gl.GlFence;
import com.jozufozu.flywheel.backend.gl.error.GlError;
import com.jozufozu.flywheel.backend.gl.error.GlException;
import com.jozufozu.flywheel.backend.gl.versioned.GlCompat;
-public class PersistentGlBuffer extends GlBuffer implements Mappable {
+public class PersistentGlBuffer extends GlBuffer {
- private MappedBuffer buffer;
+ @Nullable
+ private MappedBuffer access;
int flags;
-
- long size;
- GlFence fence;
+ private final GlFence fence;
public PersistentGlBuffer(GlBufferType type) {
super(type);
@@ -34,47 +35,98 @@ public class PersistentGlBuffer extends GlBuffer implements Mappable {
}
@Override
- protected void alloc(long size) {
- this.size = size;
-
- if (buffer != null) {
- deleteInternal(handle());
- _create();
-
- bind();
+ public boolean ensureCapacity(long size) {
+ if (size < 0) {
+ throw new IllegalArgumentException("Size " + size + " < 0");
}
- fence.clear();
+ if (size == 0) {
+ return false;
+ }
- GlCompat.getInstance().bufferStorage.bufferStorage(type, size, flags);
+ if (this.size == 0) {
+ this.size = size;
+ bind();
+ GlCompat.getInstance().bufferStorage.bufferStorage(type, this.size, flags);
+ return true;
+ }
- ByteBuffer byteBuffer = GL30.glMapBufferRange(type.glEnum, 0, size, flags);
+ if (size > this.size) {
+ var oldSize = this.size;
+ this.size = size + growthMargin;
+
+ fence.clear();
+
+ realloc(this.size, oldSize);
+
+ access = null;
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public void upload(ByteBuffer directBuffer) {
+ ensureCapacity(directBuffer.capacity());
+
+ var access = getWriteAccess();
+
+ ByteBuffer ourBuffer = access.unwrap();
+
+ ourBuffer.reset();
+
+ MemoryUtil.memCopy(directBuffer, ourBuffer);
+
+ int uploadSize = directBuffer.remaining();
+ int ourSize = ourBuffer.capacity();
+
+ if (uploadSize < ourSize) {
+ long clearFrom = access.getMemAddress() + uploadSize;
+ MemoryUtil.memSet(clearFrom, 0, ourSize - uploadSize);
+ }
+ }
+
+ private void mapToClientMemory() {
+ bind();
+ ByteBuffer byteBuffer = GL32.glMapBufferRange(type.glEnum, 0, size, flags);
if (byteBuffer == null) {
throw new GlException(GlError.poll(), "Could not map buffer");
}
- buffer = new MappedBuffer(this, byteBuffer, 0, size);
+ access = new MappedBuffer(this, byteBuffer, 0, size);
+ }
+
+ private void realloc(long newSize, long oldSize) {
+ int oldHandle = handle();
+ int newHandle = GL32.glGenBuffers();
+
+ GlBufferType.COPY_READ_BUFFER.bind(oldHandle);
+ type.bind(newHandle);
+
+ GlCompat.getInstance().bufferStorage.bufferStorage(type, newSize, flags);
+
+ GL32.glCopyBufferSubData(GlBufferType.COPY_READ_BUFFER.glEnum, type.glEnum, 0, 0, oldSize);
+
+ delete();
+ setHandle(newHandle);
}
@Override
- public void upload(ByteBuffer directBuffer) {
- throw new UnsupportedOperationException("FIXME: Nothing calls #upload on a persistent buffer as of 12/10/2021.");
+ public MappedBuffer map() {
+ return getWriteAccess()
+ .position(0);
}
- @Override
- public MappedBuffer getBuffer(long offset, long length) {
+ private MappedBuffer getWriteAccess() {
+ if (access == null) {
+ mapToClientMemory();
+ } else {
+ fence.waitSync(); // FIXME: Hangs too much, needs double/triple buffering
+ }
- fence.waitSync();
-
- buffer.position((int) offset);
-
- return buffer;
- }
-
- @Override
- public GlBufferType getType() {
- return type;
+ return access;
}
@Override
diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/VecBuffer.java b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/VecBuffer.java
deleted file mode 100644
index 8d5a14eb6..000000000
--- a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/VecBuffer.java
+++ /dev/null
@@ -1,145 +0,0 @@
-package com.jozufozu.flywheel.backend.gl.buffer;
-
-import java.nio.Buffer;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.FloatBuffer;
-
-public class VecBuffer {
-
- protected ByteBuffer internal;
-
- public VecBuffer() {
- }
-
- public VecBuffer(ByteBuffer internal) {
- this.internal = internal;
- }
-
- public static VecBuffer allocate(int bytes) {
- ByteBuffer buffer = ByteBuffer.allocate(bytes);
- buffer.order(ByteOrder.nativeOrder());
- return new VecBuffer(buffer);
- }
-
- public ByteBuffer unwrap() {
- return internal;
- }
-
- public VecBuffer rewind() {
- ((Buffer) internal).rewind();
-
- return this;
- }
-
- public VecBuffer putFloatArray(float[] floats) {
-
- internal.asFloatBuffer().put(floats);
- internal.position(internal.position() + floats.length * 4);
-
- return this;
- }
-
- public VecBuffer putByteArray(byte[] bytes) {
- internal.put(bytes);
- return this;
- }
-
- public VecBuffer put(FloatBuffer floats) {
-
- int remainingBytes = floats.remaining() * 4;
- internal.asFloatBuffer().put(floats);
- internal.position(internal.position() + remainingBytes);
-
- return this;
- }
-
- public int position() {
- return internal.position();
- }
-
- /**
- * Position this buffer relative to the 0-index in GPU memory.
- *
- * @return This buffer.
- */
- public VecBuffer position(int p) {
- internal.position(p);
- return this;
- }
-
- public VecBuffer putFloat(float f) {
- internal.putFloat(f);
- return this;
- }
-
- public VecBuffer putInt(int i) {
- internal.putInt(i);
- return this;
- }
-
- public VecBuffer putShort(short s) {
- internal.putShort(s);
- return this;
- }
-
- public VecBuffer put(byte b) {
- internal.put(b);
- return this;
- }
-
- public VecBuffer put(ByteBuffer b) {
- internal.put(b);
- return this;
- }
-
- public VecBuffer putVec4(float x, float y, float z, float w) {
- internal.putFloat(x);
- internal.putFloat(y);
- internal.putFloat(z);
- internal.putFloat(w);
- return this;
- }
-
- public VecBuffer putColor(int r, int g, int b, int a) {
- internal.put((byte) r);
- internal.put((byte) g);
- internal.put((byte) b);
- internal.put((byte) a);
- return this;
- }
-
- public VecBuffer putColor(byte r, byte g, byte b, byte a) {
- internal.put(r);
- internal.put(g);
- internal.put(b);
- internal.put(a);
- return this;
- }
-
- public VecBuffer putVec3(float x, float y, float z) {
- internal.putFloat(x);
- internal.putFloat(y);
- internal.putFloat(z);
- return this;
- }
-
- public VecBuffer putVec2(float x, float y) {
- internal.putFloat(x);
- internal.putFloat(y);
- return this;
- }
-
- public VecBuffer putVec3(byte x, byte y, byte z) {
- internal.put(x);
- internal.put(y);
- internal.put(z);
- return this;
- }
-
- public VecBuffer putVec2(byte x, byte y) {
- internal.put(x);
- internal.put(y);
- return this;
- }
-}
diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlShader.java b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlShader.java
index a925d903d..c4195c68f 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlShader.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlShader.java
@@ -7,10 +7,11 @@ import java.util.stream.Collectors;
import org.lwjgl.opengl.GL20;
+import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.gl.GlObject;
import com.jozufozu.flywheel.backend.gl.versioned.GlCompat;
+import com.jozufozu.flywheel.core.compile.ShaderCompilationException;
import com.jozufozu.flywheel.core.shader.ShaderConstants;
-import com.jozufozu.flywheel.core.source.ShaderLoadingException;
import net.minecraft.client.Minecraft;
import net.minecraft.resources.ResourceLocation;
@@ -30,18 +31,10 @@ public class GlShader extends GlObject {
GlCompat.safeShaderSource(handle, source);
GL20.glCompileShader(handle);
- // TODO: control this via a JVM flag or other
dumpSource(source, type);
-// String log = GL20.glGetShaderInfoLog(handle);
-//
-// if (!log.isEmpty()) {
-// System.out.println(log);
-//// env.printShaderInfoLog(source, log, this.name);
-// }
-
if (GL20.glGetShaderi(handle, GL20.GL_COMPILE_STATUS) != GL20.GL_TRUE) {
- throw new ShaderLoadingException("Could not compile " + getName() + ". See log for details.");
+ throw new ShaderCompilationException("Could not compile " + getName(), handle);
}
setHandle(handle);
@@ -61,6 +54,10 @@ public class GlShader extends GlObject {
}
private void dumpSource(String source, ShaderType type) {
+ if (!Backend.dumpShaderSource) {
+ return;
+ }
+
File dir = new File(Minecraft.getInstance().gameDirectory, "flywheel_sources");
dir.mkdirs();
File file = new File(dir, type.getFileName(getName()));
diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/versioned/GlCompat.java b/src/main/java/com/jozufozu/flywheel/backend/gl/versioned/GlCompat.java
index 0aaffe754..059dd15b1 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/gl/versioned/GlCompat.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/gl/versioned/GlCompat.java
@@ -38,13 +38,7 @@ public class GlCompat {
instancedArrays = getLatest(InstancedArrays.class, caps);
bufferStorage = getLatest(BufferStorage.class, caps);
- if (Util.getPlatform() == Util.OS.WINDOWS) {
- String vendor = GL20C.glGetString(GL20C.GL_VENDOR);
- // vendor string I got was "ATI Technologies Inc."
- amd = vendor.contains("ATI") || vendor.contains("AMD");
- } else {
- amd = false;
- }
+ amd = _isAmdWindows();
}
public boolean onAMDWindows() {
@@ -82,7 +76,7 @@ public class GlCompat {
/**
* Copied from:
- *
https://github.com/grondag/canvas/commit/820bf754092ccaf8d0c169620c2ff575722d7d96
+ *
canvas
*
*
Identical in function to {@link GL20C#glShaderSource(int, CharSequence)} but
* passes a null pointer for string length to force the driver to rely on the null
@@ -107,5 +101,20 @@ public class GlCompat {
stack.setPointer(stackPointer);
}
}
+
+ private static boolean _isAmdWindows() {
+ if (Util.getPlatform() != Util.OS.WINDOWS) {
+ return false;
+ }
+
+ String vendor = GL20C.glGetString(GL20C.GL_VENDOR);
+
+ if (vendor == null) {
+ return false;
+ }
+
+ // vendor string I got was "ATI Technologies Inc."
+ return vendor.contains("ATI") || vendor.contains("AMD");
+ }
}
diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/DrawBuffer.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/DrawBuffer.java
index 4166c1e59..a9759c368 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/instancing/DrawBuffer.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/DrawBuffer.java
@@ -1,7 +1,9 @@
package com.jozufozu.flywheel.backend.instancing;
+import java.lang.ref.Cleaner;
import java.nio.ByteBuffer;
+import com.jozufozu.flywheel.backend.FlywheelMemory;
import com.jozufozu.flywheel.backend.model.BufferBuilderExtension;
import com.jozufozu.flywheel.backend.model.DirectVertexConsumer;
import com.mojang.blaze3d.platform.MemoryTracker;
@@ -14,11 +16,12 @@ import net.minecraft.client.renderer.RenderType;
*
* The number of vertices needs to be known ahead of time.
*/
-public class DrawBuffer {
+public class DrawBuffer implements AutoCloseable {
private final RenderType parent;
private ByteBuffer backingBuffer;
private int expectedVertices;
+ private Cleaner.Cleanable cleanable;
public DrawBuffer(RenderType parent) {
this.parent = parent;
@@ -43,9 +46,12 @@ public class DrawBuffer {
if (backingBuffer == null) {
backingBuffer = MemoryTracker.create(byteSize);
+ cleanable = FlywheelMemory.track(this, backingBuffer);
}
if (byteSize > backingBuffer.capacity()) {
+ cleanable.clean();
backingBuffer = MemoryTracker.resize(backingBuffer, byteSize);
+ cleanable = FlywheelMemory.track(this, backingBuffer);
}
return new DirectVertexConsumer(backingBuffer, format, vertexCount);
@@ -74,4 +80,11 @@ public class DrawBuffer {
public void reset() {
this.expectedVertices = 0;
}
+
+ @Override
+ public void close() {
+ if (cleanable != null) {
+ cleanable.clean();
+ }
+ }
}
diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java
index 75a02685c..f2ccf13de 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java
@@ -2,7 +2,6 @@ package com.jozufozu.flywheel.backend.instancing;
import java.util.List;
-import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.config.FlwCommands;
import com.jozufozu.flywheel.config.FlwConfig;
@@ -123,9 +122,6 @@ public class InstancedRenderDispatcher {
}
public static void getDebugString(List debug) {
- debug.add("");
- debug.add("Flywheel: " + Flywheel.getVersion());
-
if (Backend.isOn()) {
InstanceWorld instanceWorld = instanceWorlds.get(Minecraft.getInstance().level);
diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java
index 2886260cd..6eae582eb 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java
@@ -3,8 +3,6 @@ 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.InstanceData;
import com.jozufozu.flywheel.api.struct.InstancedStructType;
@@ -56,65 +54,48 @@ public class GPUInstancer extends AbstractInstancer {
removeDeletedInstances();
}
- vbo.bind();
-
- if (!realloc()) {
-
+ if (checkAndGrowBuffer()) {
+ // The instance vbo has moved, so we need to re-bind attributes
boundTo.clear();
-
- if (anyToRemove) {
- clearBufferTail();
- }
-
- if (anyToUpdate) {
- updateBuffer();
- }
-
- glInstanceCount = data.size();
}
+ if (anyToUpdate) {
+ clearAndUpdateBuffer();
+ }
+
+ glInstanceCount = data.size();
+
if (boundTo.add(vao)) {
bindInstanceAttributes(vao);
}
- vbo.unbind();
-
anyToRemove = anyToUpdate = false;
}
- private void clearBufferTail() {
- int size = data.size();
- final int offset = size * instanceFormat.getStride();
- final long length = vbo.getCapacity() - offset;
- if (length > 0) {
- try (MappedBuffer buf = vbo.getBuffer(offset, length)) {
- MemoryUtil.memSet(MemoryUtil.memAddress(buf.unwrap()), 0, length);
- } catch (Exception e) {
- Flywheel.LOGGER.error("Error clearing buffer tail:", e);
- }
- }
- }
-
- private void updateBuffer() {
+ private void clearAndUpdateBuffer() {
final int size = data.size();
+ final long clearStart = (long) size * instanceFormat.getStride();
+ final long clearLength = vbo.getSize() - clearStart;
- if (size <= 0) return;
+ try (MappedBuffer buf = vbo.map()) {
+ buf.clear(clearStart, clearLength);
- try (MappedBuffer mapped = vbo.getBuffer()) {
+ if (size > 0) {
- final StructWriter writer = instancedType.getWriter(mapped);
+ final StructWriter writer = instancedType.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);
+ 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(element);
- sequential = true;
- } else {
- sequential = false;
}
}
} catch (Exception e) {
@@ -122,33 +103,22 @@ public class GPUInstancer extends AbstractInstancer {
}
}
- private boolean realloc() {
+ /**
+ * @return {@code true} if the buffer moved.
+ */
+ private boolean checkAndGrowBuffer() {
int size = this.data.size();
int stride = instanceFormat.getStride();
int requiredSize = size * stride;
- if (vbo.ensureCapacity(requiredSize)) {
- try (MappedBuffer buffer = vbo.getBuffer()) {
- StructWriter writer = instancedType.getWriter(buffer);
- for (D datum : data) {
- writer.write(datum);
- }
- } catch (Exception e) {
- Flywheel.LOGGER.error("Error reallocating GPUInstancer:", e);
- }
-
- glInstanceCount = size;
-
- return true;
- }
- return false;
+ return vbo.ensureCapacity(requiredSize);
}
private void bindInstanceAttributes(GlVertexArray vao) {
- vao.bindAttributes(attributeBaseIndex, instanceFormat);
+ vao.bindAttributes(this.vbo, this.attributeBaseIndex, this.instanceFormat);
- for (int i = 0; i < instanceFormat.getAttributeCount(); i++) {
- vao.setAttributeDivisor(attributeBaseIndex + i, 1);
+ for (int i = 0; i < this.instanceFormat.getAttributeCount(); i++) {
+ vao.setAttributeDivisor(this.attributeBaseIndex + i, 1);
}
}
}
diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedModel.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedModel.java
index 6c54ec14d..18ef8a641 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedModel.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedModel.java
@@ -5,6 +5,7 @@ import java.util.Map;
import com.google.common.collect.ImmutableMap;
import com.jozufozu.flywheel.api.InstanceData;
import com.jozufozu.flywheel.api.material.Material;
+import com.jozufozu.flywheel.backend.gl.GlStateTracker;
import com.jozufozu.flywheel.backend.gl.GlVertexArray;
import com.jozufozu.flywheel.backend.model.MeshPool;
import com.jozufozu.flywheel.core.model.Mesh;
@@ -44,7 +45,7 @@ public class InstancedModel {
private Layer(MeshPool allocator, Material material, Mesh mesh) {
this.material = material;
vao = new GlVertexArray();
- bufferedMesh = allocator.alloc(mesh, vao);
+ bufferedMesh = allocator.alloc(mesh);
instancer.attributeBaseIndex = bufferedMesh.getAttributeCount();
vao.enableArrays(bufferedMesh.getAttributeCount() + instancer.instanceFormat.getAttributeCount());
}
@@ -53,16 +54,17 @@ public class InstancedModel {
public void render() {
if (invalid()) return;
- vao.bind();
+ try (var ignored = GlStateTracker.getRestoreState()) {
- instancer.renderSetup(vao);
+ instancer.renderSetup(vao);
- if (instancer.glInstanceCount > 0) {
- bufferedMesh.drawInstances(instancer.glInstanceCount);
+ if (instancer.glInstanceCount > 0) {
+ bufferedMesh.drawInstances(vao, instancer.glInstanceCount);
+ }
+
+ // persistent mapping sync point
+ instancer.vbo.doneForThisFrame();
}
-
- // persistent mapping sync point
- instancer.vbo.doneForThisFrame();
}
@Override
diff --git a/src/main/java/com/jozufozu/flywheel/backend/model/ArrayModelRenderer.java b/src/main/java/com/jozufozu/flywheel/backend/model/ArrayModelRenderer.java
index 79809edf8..36890cb5c 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/model/ArrayModelRenderer.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/model/ArrayModelRenderer.java
@@ -10,7 +10,7 @@ public class ArrayModelRenderer {
public ArrayModelRenderer(BlockMesh mesh, MeshPool meshPool) {
this.vao = new GlVertexArray();
- this.mesh = meshPool.alloc(mesh, this.vao);
+ this.mesh = meshPool.alloc(mesh);
}
/**
@@ -19,9 +19,7 @@ public class ArrayModelRenderer {
public void draw() {
if (mesh.isDeleted()) return;
- vao.bind();
-
- mesh.drawCall();
+ mesh.drawCall(vao);
}
public void delete() {
diff --git a/src/main/java/com/jozufozu/flywheel/backend/model/MeshPool.java b/src/main/java/com/jozufozu/flywheel/backend/model/MeshPool.java
index 0bcaf66b1..8ea30abc4 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/model/MeshPool.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/model/MeshPool.java
@@ -1,7 +1,9 @@
package com.jozufozu.flywheel.backend.model;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import org.lwjgl.opengl.GL32;
@@ -42,7 +44,6 @@ public class MeshPool {
vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER);
- vbo.bind();
vbo.setGrowthMargin(stride * 64);
}
@@ -50,16 +51,15 @@ public class MeshPool {
* Allocate a model in the arena.
*
* @param mesh The model to allocate.
- * @param vao The vertex array object to attach the model to.
* @return A handle to the allocated model.
*/
- public BufferedMesh alloc(Mesh mesh, GlVertexArray vao) {
- BufferedMesh bufferedModel = new BufferedMesh(vao, mesh, vertices);
+ public BufferedMesh alloc(Mesh mesh) {
+ BufferedMesh bufferedModel = new BufferedMesh(mesh, vertices);
vertices += mesh.getVertexCount();
models.add(bufferedModel);
pendingUpload.add(bufferedModel);
- setDirty();
+ dirty = true;
return bufferedModel;
}
@@ -67,13 +67,11 @@ public class MeshPool {
if (dirty) {
if (anyToRemove) processDeletions();
- vbo.bind();
if (realloc()) {
uploadAll();
} else {
uploadPending();
}
- vbo.unbind();
dirty = false;
pendingUpload.clear();
@@ -110,7 +108,7 @@ public class MeshPool {
}
private void uploadAll() {
- try (MappedBuffer buffer = vbo.getBuffer()) {
+ try (MappedBuffer buffer = vbo.map()) {
VertexWriter writer = vertexType.createWriter(buffer.unwrap());
int vertices = 0;
@@ -128,7 +126,7 @@ public class MeshPool {
}
private void uploadPending() {
- try (MappedBuffer buffer = vbo.getBuffer()) {
+ try (MappedBuffer buffer = vbo.map()) {
VertexWriter writer = vertexType.createWriter(buffer.unwrap());
for (BufferedMesh model : pendingUpload) {
model.buffer(writer);
@@ -139,10 +137,6 @@ public class MeshPool {
}
}
- private void setDirty() {
- dirty = true;
- }
-
public void delete() {
vbo.delete();
}
@@ -150,51 +144,60 @@ public class MeshPool {
public class BufferedMesh {
private final ElementBuffer ebo;
- private final GlVertexArray vao;
-
private final Mesh mesh;
private int first;
private boolean deleted;
- public BufferedMesh(GlVertexArray vao, Mesh mesh, int first) {
- this.vao = vao;
+ private final Set boundTo = new HashSet<>();
+
+ public BufferedMesh(Mesh mesh, int first) {
this.mesh = mesh;
this.first = first;
- ebo = mesh.createEBO();
+ this.ebo = mesh.createEBO();
}
- public void drawCall() {
- ebo.bind();
- GL32.glDrawElementsBaseVertex(GlPrimitive.TRIANGLES.glEnum, ebo.elementCount, ebo.eboIndexType.getGlEnum(), 0, first);
+ public void drawCall(GlVertexArray vao) {
+ attachTo(vao);
+ vao.bind();
+ this.ebo.bind();
+ GL32.glDrawElementsBaseVertex(GlPrimitive.TRIANGLES.glEnum, this.ebo.elementCount, this.ebo.eboIndexType.getGlEnum(), 0, this.first);
}
- public void drawInstances(int instanceCount) {
+ public void drawInstances(GlVertexArray vao, int instanceCount) {
if (mesh.getVertexCount() <= 0 || isDeleted()) return;
- ebo.bind();
+ attachTo(vao);
+
+ vao.bind();
+ this.ebo.bind();
//Backend.log.info(StringUtil.args("drawElementsInstancedBaseVertex", GlPrimitive.TRIANGLES, ebo.elementCount, ebo.eboIndexType, 0, instanceCount, first));
- GL32.glDrawElementsInstancedBaseVertex(GlPrimitive.TRIANGLES.glEnum, ebo.elementCount, ebo.eboIndexType.getGlEnum(), 0, instanceCount, first);
+ GL32.glDrawElementsInstancedBaseVertex(GlPrimitive.TRIANGLES.glEnum, this.ebo.elementCount, this.ebo.eboIndexType.getGlEnum(), 0, instanceCount, this.first);
+ }
+
+ private void attachTo(GlVertexArray vao) {
+ if (this.boundTo.add(vao)) {
+ vao.enableArrays(getAttributeCount());
+ vao.bindAttributes(MeshPool.this.vbo, 0, MeshPool.this.vertexType.getLayout());
+ }
}
public boolean isDeleted() {
- return deleted;
+ return this.deleted;
}
public void delete() {
- setDirty();
- anyToRemove = true;
- deleted = true;
+ MeshPool.this.dirty = true;
+ MeshPool.this.anyToRemove = true;
+ this.deleted = true;
}
private void buffer(VertexWriter writer) {
- writer.seekToVertex(first);
- writer.writeVertexList(mesh.getReader());
-
- vao.enableArrays(getAttributeCount());
- vao.bindAttributes(0, vertexType.getLayout());
+ writer.seekToVertex(this.first);
+ writer.writeVertexList(this.mesh.getReader());
+ this.boundTo.clear();
}
public int getAttributeCount() {
diff --git a/src/main/java/com/jozufozu/flywheel/backend/struct/BufferWriter.java b/src/main/java/com/jozufozu/flywheel/backend/struct/BufferWriter.java
index 31a23c472..5a0bc8fb1 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/struct/BufferWriter.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/struct/BufferWriter.java
@@ -1,18 +1,19 @@
package com.jozufozu.flywheel.backend.struct;
+import java.nio.ByteBuffer;
+
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.struct.StructWriter;
-import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
public abstract class BufferWriter implements StructWriter {
- protected final VecBuffer backingBuffer;
+ protected final ByteBuffer backingBuffer;
protected final int stride;
- protected BufferWriter(VecBuffer backingBuffer, StructType vertexType) {
- this.backingBuffer = backingBuffer;
+ protected BufferWriter(StructType structType, ByteBuffer byteBuffer) {
+ this.backingBuffer = byteBuffer;
- this.stride = vertexType.getLayout().getStride();
+ this.stride = structType.getLayout().getStride();
}
@Override
diff --git a/src/main/java/com/jozufozu/flywheel/backend/struct/UnsafeBufferWriter.java b/src/main/java/com/jozufozu/flywheel/backend/struct/UnsafeBufferWriter.java
index b7c74e7f6..40d489d54 100644
--- a/src/main/java/com/jozufozu/flywheel/backend/struct/UnsafeBufferWriter.java
+++ b/src/main/java/com/jozufozu/flywheel/backend/struct/UnsafeBufferWriter.java
@@ -1,9 +1,10 @@
package com.jozufozu.flywheel.backend.struct;
+import java.nio.ByteBuffer;
+
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.struct.StructType;
-import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
/**
* This class copied/adapted from jellysquid's
@@ -20,8 +21,8 @@ public abstract class UnsafeBufferWriter extends BufferWriter {
*/
protected long writePointer;
- protected UnsafeBufferWriter(VecBuffer backingBuffer, StructType vertexType) {
- super(backingBuffer, vertexType);
+ protected UnsafeBufferWriter(StructType structType, ByteBuffer byteBuffer) {
+ super(structType, byteBuffer);
acquireWritePointer();
}
@@ -38,6 +39,6 @@ public abstract class UnsafeBufferWriter extends BufferWriter {
}
private void acquireWritePointer() {
- this.writePointer = MemoryUtil.memAddress(this.backingBuffer.unwrap(), this.backingBuffer.position());
+ this.writePointer = MemoryUtil.memAddress(this.backingBuffer, this.backingBuffer.position());
}
}
diff --git a/src/main/java/com/jozufozu/flywheel/config/FlwCommands.java b/src/main/java/com/jozufozu/flywheel/config/FlwCommands.java
index 7575111e0..18e487b4d 100644
--- a/src/main/java/com/jozufozu/flywheel/config/FlwCommands.java
+++ b/src/main/java/com/jozufozu/flywheel/config/FlwCommands.java
@@ -7,6 +7,7 @@ import org.jetbrains.annotations.NotNull;
import com.jozufozu.flywheel.backend.Backend;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
+import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import net.minecraft.ChatFormatting;
@@ -14,9 +15,12 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
+import net.minecraft.commands.arguments.coordinates.BlockPosArgument;
+import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.chat.TextComponent;
+import net.minecraft.world.entity.Entity;
import net.minecraftforge.client.event.RegisterClientCommandsEvent;
import net.minecraftforge.common.ForgeConfigSpec.ConfigValue;
import net.minecraftforge.fml.ModList;
@@ -87,6 +91,25 @@ public class FlwCommands {
}
));
+ commandBuilder.command.then(Commands.literal("debugCrumble")
+ .then(Commands.argument("pos", BlockPosArgument.blockPos())
+ .then(Commands.argument("stage", IntegerArgumentType.integer(0, 9))
+ .executes(context -> {
+ BlockPos pos = BlockPosArgument.getLoadedBlockPos(context, "pos");
+ int value = IntegerArgumentType.getInteger(context, "stage");
+
+ Entity executor = context.getSource()
+ .getEntity();
+
+ if (executor == null) {
+ return 0;
+ }
+
+ executor.level.destroyBlockProgress(executor.getId(), pos, value);
+
+ return 1;
+ }))));
+
commandBuilder.build(event.getDispatcher());
}
diff --git a/src/main/java/com/jozufozu/flywheel/core/FullscreenQuad.java b/src/main/java/com/jozufozu/flywheel/core/FullscreenQuad.java
index e319fdf2c..b5a34c28a 100644
--- a/src/main/java/com/jozufozu/flywheel/core/FullscreenQuad.java
+++ b/src/main/java/com/jozufozu/flywheel/core/FullscreenQuad.java
@@ -6,16 +6,22 @@ import static org.lwjgl.opengl.GL20.glVertexAttribPointer;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.backend.gl.GlNumericType;
+import com.jozufozu.flywheel.backend.gl.GlStateTracker;
import com.jozufozu.flywheel.backend.gl.GlVertexArray;
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
+import com.jozufozu.flywheel.core.layout.BufferLayout;
+import com.jozufozu.flywheel.core.layout.CommonItems;
import com.jozufozu.flywheel.util.Lazy;
public class FullscreenQuad {
public static final Lazy INSTANCE = Lazy.of(FullscreenQuad::new);
+ private static final BufferLayout LAYOUT = BufferLayout.builder()
+ .addItems(CommonItems.VEC4)
+ .build();
private static final float[] vertices = {
// pos // tex
@@ -29,24 +35,25 @@ public class FullscreenQuad {
private final GlBuffer vbo;
private FullscreenQuad() {
- vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER);
- vbo.bind();
- vbo.ensureCapacity(bufferSize);
- try (MappedBuffer buffer = vbo.getBuffer()) {
- buffer.putFloatArray(vertices);
- } catch (Exception e) {
- Flywheel.LOGGER.error("Could not create fullscreen quad.", e);
+ try (var restoreState = GlStateTracker.getRestoreState()) {
+ vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER);
+ vbo.ensureCapacity(bufferSize);
+ try (MappedBuffer buffer = vbo.map()) {
+
+ buffer.unwrap()
+ .asFloatBuffer()
+ .put(vertices);
+
+ } catch (Exception e) {
+ Flywheel.LOGGER.error("Could not create fullscreen quad.", e);
+ }
+
+ vao = new GlVertexArray();
+
+ vao.enableArrays(1);
+
+ vao.bindAttributes(vbo, 0, LAYOUT);
}
-
- vao = new GlVertexArray();
- vao.bind();
-
- vao.enableArrays(1);
-
- glVertexAttribPointer(0, 4, GlNumericType.FLOAT.getGlEnum(), false, 4 * 4, 0);
-
- GlVertexArray.unbind();
- vbo.unbind();
}
public void draw() {
diff --git a/src/main/java/com/jozufozu/flywheel/core/QuadConverter.java b/src/main/java/com/jozufozu/flywheel/core/QuadConverter.java
index 100c2e168..537db4dd7 100644
--- a/src/main/java/com/jozufozu/flywheel/core/QuadConverter.java
+++ b/src/main/java/com/jozufozu/flywheel/core/QuadConverter.java
@@ -3,17 +3,14 @@ package com.jozufozu.flywheel.core;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
-import java.util.EnumMap;
-import java.util.Map;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.backend.gl.GlNumericType;
-import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
+import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
import com.jozufozu.flywheel.backend.model.ElementBuffer;
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
@@ -29,14 +26,12 @@ import net.minecraftforge.fml.common.Mod;
@Mod.EventBusSubscriber(Dist.CLIENT)
public class QuadConverter {
- public static final int STARTING_CAPACITY = 42; // 255 / 6 = 42
-
private static QuadConverter INSTANCE;
@NotNull
public static QuadConverter getInstance() {
if (INSTANCE == null) {
- INSTANCE = new QuadConverter(STARTING_CAPACITY);
+ INSTANCE = new QuadConverter();
}
return INSTANCE;
@@ -47,130 +42,80 @@ public class QuadConverter {
return INSTANCE;
}
- Map ebos;
- int[] capacities;
+ private MappedGlBuffer ebo;
+ private int quadCapacity;
- public QuadConverter(int initialCapacity) {
- this.ebos = new EnumMap<>(GlNumericType.class);
- initCapacities();
-
- fillBuffer(initialCapacity);
+ public QuadConverter() {
+ this.ebo = new MappedGlBuffer(GlBufferType.ELEMENT_ARRAY_BUFFER);
+ this.quadCapacity = 0;
}
public ElementBuffer quads2Tris(int quads) {
int indexCount = quads * 6;
- GlNumericType type = getSmallestIndexType(indexCount);
- if (quads > getCapacity(type)) {
- fillBuffer(quads, indexCount, type);
+ if (quads > quadCapacity) {
+ ebo.ensureCapacity((long) indexCount * GlNumericType.UINT.getByteWidth());
+
+ try (MappedBuffer map = ebo.map()) {
+ ByteBuffer indices = map.unwrap();
+
+ fillBuffer(indices, quads);
+ }
+ ebo.unbind();
+
+ this.quadCapacity = quads;
}
- return new ElementBuffer(getBuffer(type), indexCount, type);
- }
-
- private void initCapacities() {
- this.capacities = new int[GlNumericType.values().length];
- }
-
- private int getCapacity(GlNumericType type) {
- return capacities[type.ordinal()];
- }
-
- private void updateCapacity(GlNumericType type, int capacity) {
- if (getCapacity(type) < capacity) {
- capacities[type.ordinal()] = capacity;
- }
+ return new ElementBuffer(ebo, indexCount, GlNumericType.UINT);
}
public void delete() {
- ebos.values()
- .forEach(GlBuffer::delete);
- ebos.clear();
- initCapacities();
+ ebo.delete();
+ this.quadCapacity = 0;
}
- private void fillBuffer(int quads) {
- int indexCount = quads * 6;
+ private void fillBuffer(ByteBuffer indices, int quads) {
+ long addr = MemoryUtil.memAddress(indices);
+ int numVertices = 4 * quads;
+ int baseVertex = 0;
+ while (baseVertex < numVertices) {
+ // writeQuadIndices(indices, baseVertex);
+ writeQuadIndicesUnsafe(addr, baseVertex);
- fillBuffer(quads, indexCount, getSmallestIndexType(indexCount));
- }
-
- private void fillBuffer(int quads, int indexCount, GlNumericType type) {
- MemoryStack stack = MemoryStack.stackPush();
- int bytes = indexCount * type.getByteWidth();
-
- ByteBuffer indices;
- if (bytes > stack.getSize()) {
- indices = MemoryUtil.memAlloc(bytes); // not enough space on the preallocated stack
- } else {
- stack.push();
- indices = stack.malloc(bytes);
+ baseVertex += 4;
+ addr += 6 * 4;
}
-
- indices.order(ByteOrder.nativeOrder());
-
- fillBuffer(indices, type, quads);
-
- GlBuffer buffer = getBuffer(type);
-
- buffer.bind();
- buffer.upload(indices);
- buffer.unbind();
-
- if (bytes > stack.getSize()) {
- MemoryUtil.memFree(indices);
- } else {
- stack.pop();
- }
-
- updateCapacity(type, quads);
+ // ((Buffer) indices).flip();
}
- private void fillBuffer(ByteBuffer indices, GlNumericType type, int quads) {
- for (int i = 0, max = 4 * quads; i < max; i += 4) {
- // triangle a
- type.castAndBuffer(indices, i);
- type.castAndBuffer(indices, i + 1);
- type.castAndBuffer(indices, i + 2);
- // triangle b
- type.castAndBuffer(indices, i);
- type.castAndBuffer(indices, i + 2);
- type.castAndBuffer(indices, i + 3);
- }
- ((Buffer) indices).flip();
+ private void writeQuadIndices(ByteBuffer indices, int baseVertex) {
+ // triangle a
+ indices.putInt(baseVertex);
+ indices.putInt(baseVertex + 1);
+ indices.putInt(baseVertex + 2);
+ // triangle b
+ indices.putInt(baseVertex);
+ indices.putInt(baseVertex + 2);
+ indices.putInt(baseVertex + 3);
}
- private GlBuffer getBuffer(GlNumericType type) {
- return ebos.computeIfAbsent(type, $ -> new MappedGlBuffer(GlBufferType.ELEMENT_ARRAY_BUFFER));
- }
-
- /**
- * Given the needed number of indices, what is the smallest bit width type that can index everything?
- *
- *
- * | indexCount | type |
- * |--------------|-------|
- * | [0, 255) | byte |
- * | [256, 65536) | short |
- * | [65537, ) | int |
- *
- */
- private static GlNumericType getSmallestIndexType(int indexCount) {
-// indexCount = indexCount >>> 8;
-// if (indexCount == 0) {
-// return GlNumericType.UBYTE;
-// }
-// indexCount = indexCount >>> 8;
-// if (indexCount == 0) {
-// return GlNumericType.USHORT;
-// }
-
- return GlNumericType.UINT;
+ private void writeQuadIndicesUnsafe(long addr, int baseVertex) {
+ // triangle a
+ MemoryUtil.memPutInt(addr, baseVertex);
+ MemoryUtil.memPutInt(addr + 4, baseVertex + 1);
+ MemoryUtil.memPutInt(addr + 8, baseVertex + 2);
+ // triangle b
+ MemoryUtil.memPutInt(addr + 12, baseVertex);
+ MemoryUtil.memPutInt(addr + 16, baseVertex + 2);
+ MemoryUtil.memPutInt(addr + 20, baseVertex + 3);
}
// make sure this gets reset first so it has a chance to repopulate
@SubscribeEvent(priority = EventPriority.HIGHEST)
public static void onRendererReload(ReloadRenderersEvent event) {
- if (INSTANCE != null) INSTANCE.delete();
+ if (INSTANCE != null) {
+ INSTANCE.delete();
+ INSTANCE = null;
+ }
}
}
diff --git a/src/main/java/com/jozufozu/flywheel/core/compile/FragmentCompiler.java b/src/main/java/com/jozufozu/flywheel/core/compile/FragmentCompiler.java
index 0c925373f..8fd766456 100644
--- a/src/main/java/com/jozufozu/flywheel/core/compile/FragmentCompiler.java
+++ b/src/main/java/com/jozufozu/flywheel/core/compile/FragmentCompiler.java
@@ -7,7 +7,7 @@ import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
import com.jozufozu.flywheel.core.CoreShaderInfoMap.CoreShaderInfo.FogType;
import com.jozufozu.flywheel.core.shader.ShaderConstants;
import com.jozufozu.flywheel.core.shader.StateSnapshot;
-import com.jozufozu.flywheel.core.source.FileIndexImpl;
+import com.jozufozu.flywheel.core.source.FileIndex;
import com.jozufozu.flywheel.core.source.FileResolution;
import com.jozufozu.flywheel.core.source.SourceFile;
@@ -33,7 +33,7 @@ public class FragmentCompiler extends Memoizer {
shaderConstants.writeInto(finalSource);
finalSource.append('\n');
- var index = new FileIndexImpl();
+ var index = new FileIndex();
// LAYOUT
@@ -64,7 +64,11 @@ public class VertexCompiler extends Memoizer {
.orElseThrow();
finalSource.append(generateFooter(key.vertexType, instanceStruct));
- return new GlShader(finalSource.toString(), ShaderType.VERTEX, ImmutableList.of(layoutShader.name, instanceShader.name, materialShader.name, contextShaderSource.name), shaderConstants);
+ try {
+ return new GlShader(finalSource.toString(), ShaderType.VERTEX, ImmutableList.of(layoutShader.name, instanceShader.name, materialShader.name, contextShaderSource.name), shaderConstants);
+ } catch (ShaderCompilationException e) {
+ throw e.withErrorLog(index);
+ }
}
protected String generateFooter(VertexType vertexType, ShaderStruct instance) {
diff --git a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingRenderer.java b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingRenderer.java
index 5a9906a34..9dc640d71 100644
--- a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingRenderer.java
+++ b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingRenderer.java
@@ -61,20 +61,19 @@ public class CrumblingRenderer {
Int2ObjectMap> activeStages = getActiveStageBlockEntities(levelRenderer, level);
if (activeStages.isEmpty()) return;
- GlStateTracker.State restoreState = GlStateTracker.getRestoreState();
+ try (var restoreState = GlStateTracker.getRestoreState()) {
- Matrix4f viewProjection = poseStack.last()
- .pose()
- .copy();
- viewProjection.multiplyBackward(projectionMatrix);
+ Matrix4f viewProjection = poseStack.last()
+ .pose()
+ .copy();
+ viewProjection.multiplyBackward(projectionMatrix);
- State state = STATE.get();
- var instanceManager = state.instanceManager;
- var engine = state.instancerManager;
+ State state = STATE.get();
+ var instanceManager = state.instanceManager;
+ var engine = state.instancerManager;
- renderCrumblingInner(activeStages, instanceManager, engine, level, poseStack, camera, viewProjection);
-
- restoreState.restore();
+ renderCrumblingInner(activeStages, instanceManager, engine, level, poseStack, camera, viewProjection);
+ }
}
private static void renderCrumblingInner(Int2ObjectMap> activeStages, InstanceManager instanceManager, CrumblingEngine engine, ClientLevel level, PoseStack stack, Camera camera, Matrix4f viewProjection) {
diff --git a/src/main/java/com/jozufozu/flywheel/core/hardcoded/ModelPart.java b/src/main/java/com/jozufozu/flywheel/core/hardcoded/ModelPart.java
index a30b26547..4d2f94202 100644
--- a/src/main/java/com/jozufozu/flywheel/core/hardcoded/ModelPart.java
+++ b/src/main/java/com/jozufozu/flywheel/core/hardcoded/ModelPart.java
@@ -2,6 +2,8 @@ package com.jozufozu.flywheel.core.hardcoded;
import java.util.List;
+import org.lwjgl.system.MemoryStack;
+
import com.jozufozu.flywheel.api.vertex.VertexList;
import com.jozufozu.flywheel.core.model.Mesh;
import com.jozufozu.flywheel.core.vertex.Formats;
@@ -26,12 +28,14 @@ public class ModelPart implements Mesh {
this.vertices = vertices;
}
- PosTexNormalWriterUnsafe writer = getType().createWriter(MemoryTracker.create(size()));
- for (PartBuilder.CuboidBuilder cuboid : cuboids) {
- cuboid.buffer(writer);
- }
+ try (var stack = MemoryStack.stackPush()) {
+ PosTexNormalWriterUnsafe writer = getType().createWriter(stack.malloc(size()));
+ for (PartBuilder.CuboidBuilder cuboid : cuboids) {
+ cuboid.buffer(writer);
+ }
- reader = writer.intoReader();
+ reader = writer.intoReader();
+ }
}
public static PartBuilder builder(String name, int sizeU, int sizeV) {
diff --git a/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java b/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java
index 260a8adf6..8c5e4342b 100644
--- a/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java
+++ b/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java
@@ -1,6 +1,7 @@
package com.jozufozu.flywheel.core.model;
import java.lang.reflect.Field;
+import java.nio.ByteBuffer;
import java.util.EnumMap;
import java.util.Random;
@@ -10,6 +11,7 @@ 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.datafixers.util.Pair;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.RenderType;
@@ -52,24 +54,17 @@ public class ModelUtil {
return new WorldModelBuilder(layer);
}
- public static ShadeSeparatedBufferBuilder getBufferBuilder(Bufferable object) {
+ public static ShadeSeparatedBufferBuilder getBufferBuilder(Bufferable bufferable) {
ModelBlockRenderer blockRenderer = VANILLA_RENDERER.getModelRenderer();
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
- ShadeSeparatedBufferBuilder builder = new ShadeSeparatedBufferBuilder(512);
+ objects.begin();
- builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
- objects.unshadedBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
- objects.shadeSeparatingWrapper.prepare(builder, objects.unshadedBuilder);
+ bufferable.bufferInto(blockRenderer, objects.shadeSeparatingWrapper, objects.random);
- object.bufferInto(blockRenderer, objects.shadeSeparatingWrapper, objects.random);
+ objects.end();
- objects.shadeSeparatingWrapper.clear();
- objects.unshadedBuilder.end();
- builder.appendUnshadedVertices(objects.unshadedBuilder);
- builder.end();
-
- return builder;
+ return objects.separatedBufferBuilder;
}
private static PoseStack createRotation(Direction facing) {
@@ -96,7 +91,21 @@ 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 unshadedBuilder = new BufferBuilder(512);
+
+ private void begin() {
+ this.separatedBufferBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
+ this.unshadedBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
+ this.shadeSeparatingWrapper.prepare(this.separatedBufferBuilder, this.unshadedBuilder);
+ }
+
+ private void end() {
+ this.shadeSeparatingWrapper.clear();
+ this.unshadedBuilder.end();
+ this.separatedBufferBuilder.appendUnshadedVertices(this.unshadedBuilder);
+ this.separatedBufferBuilder.end();
+ }
}
}
diff --git a/src/main/java/com/jozufozu/flywheel/core/source/FileIndex.java b/src/main/java/com/jozufozu/flywheel/core/source/FileIndex.java
index 55d91a96a..b2c5a9b6e 100644
--- a/src/main/java/com/jozufozu/flywheel/core/source/FileIndex.java
+++ b/src/main/java/com/jozufozu/flywheel/core/source/FileIndex.java
@@ -1,21 +1,68 @@
package com.jozufozu.flywheel.core.source;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jetbrains.annotations.Nullable;
+
+import com.jozufozu.flywheel.core.source.error.ErrorBuilder;
import com.jozufozu.flywheel.core.source.span.Span;
-public interface FileIndex {
+public class FileIndex {
+ public final List files = new ArrayList<>();
+
/**
* Returns an arbitrary file ID for use this compilation context, or generates one if missing.
- *
* @param sourceFile The file to retrieve the ID for.
* @return A file ID unique to the given sourceFile.
*/
- int getFileID(SourceFile sourceFile);
+ public int getFileID(SourceFile sourceFile) {
+ int i = files.indexOf(sourceFile);
+ if (i != -1) {
+ return i;
+ }
- boolean exists(SourceFile sourceFile);
+ int size = files.size();
+ files.add(sourceFile);
+ return size;
+ }
- SourceFile getFile(int fileID);
+ public boolean exists(SourceFile sourceFile) {
+ return files.contains(sourceFile);
+ }
- default Span getLineSpan(int fileId, int lineNo) {
+ public SourceFile getFile(int fileId) {
+ return files.get(fileId);
+ }
+
+ public String parseErrors(String log) {
+ List lines = log.lines()
+ .toList();
+
+ StringBuilder errors = new StringBuilder();
+ for (String line : lines) {
+ ErrorBuilder builder = parseCompilerError(line);
+
+ if (builder != null) {
+ errors.append(builder.build());
+ } else {
+ errors.append(line).append('\n');
+ }
+ }
+ return errors.toString();
+ }
+
+ @Nullable
+ private ErrorBuilder parseCompilerError(String line) {
+ try {
+ return ErrorBuilder.fromLogLine(this, line);
+ } catch (Exception ignored) {
+ }
+
+ return null;
+ }
+
+ public Span getLineSpan(int fileId, int lineNo) {
return getFile(fileId).getLineSpanNoWhitespace(lineNo);
}
}
diff --git a/src/main/java/com/jozufozu/flywheel/core/source/FileIndexImpl.java b/src/main/java/com/jozufozu/flywheel/core/source/FileIndexImpl.java
deleted file mode 100644
index fcab6d684..000000000
--- a/src/main/java/com/jozufozu/flywheel/core/source/FileIndexImpl.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package com.jozufozu.flywheel.core.source;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.jetbrains.annotations.Nullable;
-
-import com.jozufozu.flywheel.backend.Backend;
-import com.jozufozu.flywheel.core.source.error.ErrorBuilder;
-import com.jozufozu.flywheel.core.source.error.ErrorReporter;
-
-import net.minecraft.resources.ResourceLocation;
-
-public class FileIndexImpl implements FileIndex {
- public final List files = new ArrayList<>();
-
- /**
- * Returns an arbitrary file ID for use this compilation context, or generates one if missing.
- * @param sourceFile The file to retrieve the ID for.
- * @return A file ID unique to the given sourceFile.
- */
- @Override
- public int getFileID(SourceFile sourceFile) {
- int i = files.indexOf(sourceFile);
- if (i != -1) {
- return i;
- }
-
- int size = files.size();
- files.add(sourceFile);
- return size;
- }
-
- @Override
- public boolean exists(SourceFile sourceFile) {
- return files.contains(sourceFile);
- }
-
- @Override
- public SourceFile getFile(int fileId) {
- return files.get(fileId);
- }
-
- public void printShaderInfoLog(String source, String log, ResourceLocation name) {
- List lines = log.lines()
- .toList();
-
- boolean needsSourceDump = false;
-
- StringBuilder errors = new StringBuilder();
- for (String line : lines) {
- ErrorBuilder builder = parseCompilerError(line);
-
- if (builder != null) {
- errors.append(builder.build());
- } else {
- errors.append(line).append('\n');
- needsSourceDump = true;
- }
- }
- Backend.LOGGER.error("Errors compiling '" + name + "': \n" + errors);
- if (needsSourceDump) {
- // TODO: generated code gets its own "file"
- ErrorReporter.printLines(source);
- }
- }
-
- @Nullable
- private ErrorBuilder parseCompilerError(String line) {
- try {
- return ErrorBuilder.fromLogLine(this, line);
- } catch (Exception ignored) {
- }
-
- return null;
- }
-}
diff --git a/src/main/java/com/jozufozu/flywheel/core/structs/BasicWriterUnsafe.java b/src/main/java/com/jozufozu/flywheel/core/structs/BasicWriterUnsafe.java
index c29d3e057..5a7fa37c3 100644
--- a/src/main/java/com/jozufozu/flywheel/core/structs/BasicWriterUnsafe.java
+++ b/src/main/java/com/jozufozu/flywheel/core/structs/BasicWriterUnsafe.java
@@ -1,15 +1,16 @@
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.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.backend.struct.UnsafeBufferWriter;
public abstract class BasicWriterUnsafe extends UnsafeBufferWriter {
- public BasicWriterUnsafe(VecBuffer backingBuffer, StructType vertexType) {
- super(backingBuffer, vertexType);
+ public BasicWriterUnsafe(StructType structType, ByteBuffer byteBuffer) {
+ super(structType, byteBuffer);
}
@Override
diff --git a/src/main/java/com/jozufozu/flywheel/core/structs/model/ModelType.java b/src/main/java/com/jozufozu/flywheel/core/structs/model/ModelType.java
index e6547a3eb..660ebd611 100644
--- a/src/main/java/com/jozufozu/flywheel/core/structs/model/ModelType.java
+++ b/src/main/java/com/jozufozu/flywheel/core/structs/model/ModelType.java
@@ -1,9 +1,10 @@
package com.jozufozu.flywheel.core.structs.model;
+import java.nio.ByteBuffer;
+
import com.jozufozu.flywheel.api.struct.BatchedStructType;
import com.jozufozu.flywheel.api.struct.InstancedStructType;
import com.jozufozu.flywheel.api.struct.StructWriter;
-import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.core.layout.BufferLayout;
import com.jozufozu.flywheel.core.layout.CommonItems;
import com.jozufozu.flywheel.core.model.ModelTransformer;
@@ -28,8 +29,8 @@ public class ModelType implements InstancedStructType, BatchedStructT
}
@Override
- public StructWriter getWriter(VecBuffer backing) {
- return new ModelWriterUnsafe(backing, this);
+ public StructWriter getWriter(ByteBuffer backing) {
+ return new ModelWriterUnsafe(this, backing);
}
@Override
diff --git a/src/main/java/com/jozufozu/flywheel/core/structs/model/ModelWriterUnsafe.java b/src/main/java/com/jozufozu/flywheel/core/structs/model/ModelWriterUnsafe.java
index b125b8d6c..26b12801a 100644
--- a/src/main/java/com/jozufozu/flywheel/core/structs/model/ModelWriterUnsafe.java
+++ b/src/main/java/com/jozufozu/flywheel/core/structs/model/ModelWriterUnsafe.java
@@ -1,14 +1,15 @@
package com.jozufozu.flywheel.core.structs.model;
+import java.nio.ByteBuffer;
+
import com.jozufozu.flywheel.api.struct.StructType;
-import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.core.structs.BasicWriterUnsafe;
import com.jozufozu.flywheel.util.MatrixWrite;
public class ModelWriterUnsafe extends BasicWriterUnsafe {
- public ModelWriterUnsafe(VecBuffer backingBuffer, StructType vertexType) {
- super(backingBuffer, vertexType);
+ public ModelWriterUnsafe(StructType structType, ByteBuffer byteBuffer) {
+ super(structType, byteBuffer);
}
@Override
diff --git a/src/main/java/com/jozufozu/flywheel/core/structs/oriented/OrientedType.java b/src/main/java/com/jozufozu/flywheel/core/structs/oriented/OrientedType.java
index 07428287b..0c00fe649 100644
--- a/src/main/java/com/jozufozu/flywheel/core/structs/oriented/OrientedType.java
+++ b/src/main/java/com/jozufozu/flywheel/core/structs/oriented/OrientedType.java
@@ -1,9 +1,10 @@
package com.jozufozu.flywheel.core.structs.oriented;
+import java.nio.ByteBuffer;
+
import com.jozufozu.flywheel.api.struct.BatchedStructType;
import com.jozufozu.flywheel.api.struct.InstancedStructType;
import com.jozufozu.flywheel.api.struct.StructWriter;
-import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.core.layout.BufferLayout;
import com.jozufozu.flywheel.core.layout.CommonItems;
import com.jozufozu.flywheel.core.model.ModelTransformer;
@@ -29,8 +30,8 @@ public class OrientedType implements InstancedStructType, BatchedS
}
@Override
- public StructWriter getWriter(VecBuffer backing) {
- return new OrientedWriterUnsafe(backing, this);
+ public StructWriter getWriter(ByteBuffer backing) {
+ return new OrientedWriterUnsafe(this, backing);
}
@Override
diff --git a/src/main/java/com/jozufozu/flywheel/core/structs/oriented/OrientedWriterUnsafe.java b/src/main/java/com/jozufozu/flywheel/core/structs/oriented/OrientedWriterUnsafe.java
index 45730aca1..8f030f837 100644
--- a/src/main/java/com/jozufozu/flywheel/core/structs/oriented/OrientedWriterUnsafe.java
+++ b/src/main/java/com/jozufozu/flywheel/core/structs/oriented/OrientedWriterUnsafe.java
@@ -1,14 +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.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.core.structs.BasicWriterUnsafe;
public class OrientedWriterUnsafe extends BasicWriterUnsafe {
- public OrientedWriterUnsafe(VecBuffer backingBuffer, StructType vertexType) {
- super(backingBuffer, vertexType);
+ public OrientedWriterUnsafe(StructType structType, ByteBuffer byteBuffer) {
+ super(structType, byteBuffer);
}
@Override
diff --git a/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertexListUnsafe.java b/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertexListUnsafe.java
index 7258b3af4..a3d6e5930 100644
--- a/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertexListUnsafe.java
+++ b/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertexListUnsafe.java
@@ -1,35 +1,24 @@
package com.jozufozu.flywheel.core.vertex;
+import java.lang.ref.Cleaner;
import java.nio.ByteBuffer;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.vertex.ShadedVertexList;
-import com.jozufozu.flywheel.api.vertex.VertexList;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.util.RenderMath;
-public class BlockVertexListUnsafe implements VertexList {
-
- private final ByteBuffer buffer;
- private final int vertexCount;
- private final long base;
+public class BlockVertexListUnsafe extends TrackedVertexList {
public BlockVertexListUnsafe(ByteBuffer buffer, int vertexCount) {
- this.buffer = buffer;
- this.base = MemoryUtil.memAddress(buffer);
- this.vertexCount = vertexCount;
+ super(buffer, vertexCount);
}
private long ptr(long index) {
return base + index * 32;
}
- @Override
- public boolean isEmpty() {
- return vertexCount == 0;
- }
-
@Override
public float getX(int index) {
return MemoryUtil.memGetFloat(ptr(index));
@@ -95,11 +84,6 @@ public class BlockVertexListUnsafe implements VertexList {
return RenderMath.f(MemoryUtil.memGetByte(ptr(index) + 30));
}
- @Override
- public int getVertexCount() {
- return vertexCount;
- }
-
@Override
public VertexType getVertexType() {
return Formats.BLOCK;
diff --git a/src/main/java/com/jozufozu/flywheel/core/vertex/PosTexNormalVertexListUnsafe.java b/src/main/java/com/jozufozu/flywheel/core/vertex/PosTexNormalVertexListUnsafe.java
index df6aa57cd..d01249a64 100644
--- a/src/main/java/com/jozufozu/flywheel/core/vertex/PosTexNormalVertexListUnsafe.java
+++ b/src/main/java/com/jozufozu/flywheel/core/vertex/PosTexNormalVertexListUnsafe.java
@@ -1,23 +1,20 @@
package com.jozufozu.flywheel.core.vertex;
+import java.lang.ref.Cleaner;
import java.nio.ByteBuffer;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.vertex.VertexList;
import com.jozufozu.flywheel.api.vertex.VertexType;
+import com.jozufozu.flywheel.backend.FlywheelMemory;
import com.jozufozu.flywheel.util.RenderMath;
+import com.mojang.blaze3d.platform.MemoryTracker;
-public class PosTexNormalVertexListUnsafe implements VertexList {
-
- private final ByteBuffer buffer;
- private final int vertexCount;
- private final long base;
+public class PosTexNormalVertexListUnsafe extends TrackedVertexList {
public PosTexNormalVertexListUnsafe(ByteBuffer buffer, int vertexCount) {
- this.buffer = buffer;
- this.vertexCount = vertexCount;
- this.base = MemoryUtil.memAddress(buffer);
+ super(buffer, vertexCount);
}
private long ptr(long idx) {
@@ -89,11 +86,6 @@ public class PosTexNormalVertexListUnsafe implements VertexList {
return RenderMath.f(MemoryUtil.memGetByte(ptr(index) + 22));
}
- @Override
- public int getVertexCount() {
- return vertexCount;
- }
-
@Override
public VertexType getVertexType() {
return Formats.POS_TEX_NORMAL;
diff --git a/src/main/java/com/jozufozu/flywheel/core/vertex/TrackedVertexList.java b/src/main/java/com/jozufozu/flywheel/core/vertex/TrackedVertexList.java
new file mode 100644
index 000000000..00cb24eec
--- /dev/null
+++ b/src/main/java/com/jozufozu/flywheel/core/vertex/TrackedVertexList.java
@@ -0,0 +1,41 @@
+package com.jozufozu.flywheel.core.vertex;
+
+import java.lang.ref.Cleaner;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+
+import org.lwjgl.system.MemoryUtil;
+
+import com.jozufozu.flywheel.api.vertex.VertexList;
+import com.jozufozu.flywheel.backend.FlywheelMemory;
+import com.mojang.blaze3d.platform.MemoryTracker;
+
+public abstract class TrackedVertexList implements VertexList, AutoCloseable {
+
+ protected final ByteBuffer contents;
+ protected final long base;
+ protected final int vertexCount;
+ private final Cleaner.Cleanable cleanable;
+
+ protected TrackedVertexList(ByteBuffer copyFrom, int vertexCount) {
+ this.contents = MemoryTracker.create(copyFrom.capacity());
+ this.contents.order(copyFrom.order());
+ this.contents.put(copyFrom);
+ ((Buffer) this.contents).flip();
+
+ this.cleanable = FlywheelMemory.track(this, this.contents);
+
+ this.base = MemoryUtil.memAddress(this.contents);
+ this.vertexCount = vertexCount;
+ }
+
+ @Override
+ public void close() {
+ cleanable.clean();
+ }
+
+ @Override
+ public int getVertexCount() {
+ return vertexCount;
+ }
+}
diff --git a/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java b/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java
index 52e31ff9b..19ab783d8 100644
--- a/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java
+++ b/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java
@@ -1,6 +1,10 @@
package com.jozufozu.flywheel.event;
+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.light.LightUpdater;
import com.jozufozu.flywheel.util.WorldAttached;
@@ -21,7 +25,15 @@ public class ForgeEvents {
if (Minecraft.getInstance().options.renderDebug) {
- InstancedRenderDispatcher.getDebugString(event.getRight());
+ ArrayList debug = event.getRight();
+ debug.add("");
+ debug.add("Flywheel: " + Flywheel.getVersion());
+
+ InstancedRenderDispatcher.getDebugString(debug);
+
+ debug.add("Memory used:");
+ debug.add("GPU: " + FlywheelMemory.getGPUMemory());
+ debug.add("CPU: " + FlywheelMemory.getCPUMemory());
}
}
diff --git a/src/main/java/com/jozufozu/flywheel/mixin/FrustumMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/FrustumMixin.java
index ab9eaabbb..f42f4b86f 100644
--- a/src/main/java/com/jozufozu/flywheel/mixin/FrustumMixin.java
+++ b/src/main/java/com/jozufozu/flywheel/mixin/FrustumMixin.java
@@ -20,9 +20,9 @@ public class FrustumMixin {
@Inject(method = "prepare", at = @At("TAIL"))
private void onPrepare(double x, double y, double z, CallbackInfo ci) {
if (OptifineHandler.isShadowPass()) {
- GlStateTracker.State restoreState = GlStateTracker.getRestoreState();
- MinecraftForge.EVENT_BUS.post(new BeginFrameEvent(Minecraft.getInstance().level, LastActiveCamera.getActiveCamera(), (Frustum) (Object) this));
- restoreState.restore();
+ try (var restoreState = GlStateTracker.getRestoreState()) {
+ MinecraftForge.EVENT_BUS.post(new BeginFrameEvent(Minecraft.getInstance().level, LastActiveCamera.getActiveCamera(), (Frustum) (Object) this));
+ }
}
}
}
diff --git a/src/main/java/com/jozufozu/flywheel/mixin/LevelRendererMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/LevelRendererMixin.java
index f730bd77e..93fc64158 100644
--- a/src/main/java/com/jozufozu/flywheel/mixin/LevelRendererMixin.java
+++ b/src/main/java/com/jozufozu/flywheel/mixin/LevelRendererMixin.java
@@ -46,20 +46,19 @@ public class LevelRendererMixin {
Vec3 position = pCamera.getPosition();
RenderContext.CURRENT = new RenderContext(level, pPoseStack, RenderLayerEvent.createViewProjection(pPoseStack), renderBuffers, position.x, position.y, position.z);
- GlStateTracker.State restoreState = GlStateTracker.getRestoreState();
- MinecraftForge.EVENT_BUS.post(new BeginFrameEvent(level, pCamera, null));
- restoreState.restore();
+ try (var restoreState = GlStateTracker.getRestoreState()) {
+ MinecraftForge.EVENT_BUS.post(new BeginFrameEvent(level, pCamera, null));
+ }
}
@Inject(at = @At("TAIL"), method = "renderChunkLayer")
private void renderChunkLayer(RenderType pRenderType, PoseStack pPoseStack, double pCamX, double pCamY, double pCamZ, Matrix4f pProjectionMatrix, CallbackInfo ci) {
- GlStateTracker.State restoreState = GlStateTracker.getRestoreState();
+ try (var restoreState = GlStateTracker.getRestoreState()) {
- // TODO: Is this necessary?
- InstancedRenderDispatcher.renderSpecificType(RenderContext.CURRENT, pRenderType);
- MinecraftForge.EVENT_BUS.post(new RenderLayerEvent(RenderContext.CURRENT, pRenderType));
-
- restoreState.restore();
+ // TODO: Is this necessary?
+ InstancedRenderDispatcher.renderSpecificType(RenderContext.CURRENT, pRenderType);
+ MinecraftForge.EVENT_BUS.post(new RenderLayerEvent(RenderContext.CURRENT, pRenderType));
+ }
}
@Inject(at = @At("TAIL"), method = "renderLevel")
diff --git a/src/main/java/com/jozufozu/flywheel/mixin/MultiBufferSourceMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/MultiBufferSourceMixin.java
index 7af64e9c3..ae7d1a77a 100644
--- a/src/main/java/com/jozufozu/flywheel/mixin/MultiBufferSourceMixin.java
+++ b/src/main/java/com/jozufozu/flywheel/mixin/MultiBufferSourceMixin.java
@@ -19,22 +19,20 @@ public class MultiBufferSourceMixin {
@Inject(method = "endBatch(Lnet/minecraft/client/renderer/RenderType;)V", at = @At("TAIL"))
private void renderLayer(RenderType renderType, CallbackInfo ci) {
if (RenderContext.CURRENT != null && Backend.isGameActive() && Backend.isOn()) {
- GlStateTracker.State restoreState = GlStateTracker.getRestoreState();
+ try (var restoreState = GlStateTracker.getRestoreState()) {
- InstancedRenderDispatcher.renderSpecificType(RenderContext.CURRENT, renderType);
+ InstancedRenderDispatcher.renderSpecificType(RenderContext.CURRENT, renderType);
- restoreState.restore();
+ }
}
}
@Inject(method = "endBatch()V", at = @At("TAIL"))
private void endBatch(CallbackInfo ci) {
if (RenderContext.CURRENT != null && Backend.isGameActive() && Backend.isOn()) {
- GlStateTracker.State restoreState = GlStateTracker.getRestoreState();
-
- InstancedRenderDispatcher.renderAllRemaining(RenderContext.CURRENT);
-
- restoreState.restore();
+ try (var restoreState = GlStateTracker.getRestoreState()) {
+ InstancedRenderDispatcher.renderAllRemaining(RenderContext.CURRENT);
+ }
}
}
}
diff --git a/src/main/java/com/jozufozu/flywheel/mixin/matrix/Matrix3fMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/matrix/Matrix3fMixin.java
index a6057dc0c..b8cbadd0d 100644
--- a/src/main/java/com/jozufozu/flywheel/mixin/matrix/Matrix3fMixin.java
+++ b/src/main/java/com/jozufozu/flywheel/mixin/matrix/Matrix3fMixin.java
@@ -1,10 +1,11 @@
package com.jozufozu.flywheel.mixin.matrix;
+import java.nio.ByteBuffer;
+
import org.lwjgl.system.MemoryUtil;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
-import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.util.MatrixWrite;
import com.mojang.math.Matrix3f;
@@ -35,7 +36,7 @@ public abstract class Matrix3fMixin implements MatrixWrite {
}
@Override
- public void flywheel$write(VecBuffer buffer) {
+ public void flywheel$write(ByteBuffer buffer) {
buffer.putFloat(m00);
buffer.putFloat(m10);
buffer.putFloat(m20);
diff --git a/src/main/java/com/jozufozu/flywheel/mixin/matrix/Matrix4fMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/matrix/Matrix4fMixin.java
index e97fa3e8d..14f64c9b0 100644
--- a/src/main/java/com/jozufozu/flywheel/mixin/matrix/Matrix4fMixin.java
+++ b/src/main/java/com/jozufozu/flywheel/mixin/matrix/Matrix4fMixin.java
@@ -1,10 +1,11 @@
package com.jozufozu.flywheel.mixin.matrix;
+import java.nio.ByteBuffer;
+
import org.lwjgl.system.MemoryUtil;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
-import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.util.MatrixWrite;
import com.mojang.math.Matrix4f;
@@ -49,7 +50,7 @@ public abstract class Matrix4fMixin implements MatrixWrite {
}
@Override
- public void flywheel$write(VecBuffer buf) {
+ public void flywheel$write(ByteBuffer buf) {
buf.putFloat(m00);
buf.putFloat(m10);
buf.putFloat(m20);
diff --git a/src/main/java/com/jozufozu/flywheel/util/MatrixWrite.java b/src/main/java/com/jozufozu/flywheel/util/MatrixWrite.java
index 0619d0793..9af8c92bc 100644
--- a/src/main/java/com/jozufozu/flywheel/util/MatrixWrite.java
+++ b/src/main/java/com/jozufozu/flywheel/util/MatrixWrite.java
@@ -1,6 +1,6 @@
package com.jozufozu.flywheel.util;
-import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
+import java.nio.ByteBuffer;
/**
* @see com.jozufozu.flywheel.mixin.matrix.Matrix3fMixin
@@ -13,5 +13,5 @@ public interface MatrixWrite {
*/
void flywheel$writeUnsafe(long ptr);
- void flywheel$write(VecBuffer buf);
+ void flywheel$write(ByteBuffer buf);
}
diff --git a/src/main/resources/assets/flywheel/flywheel/context/crumbling.frag b/src/main/resources/assets/flywheel/flywheel/context/crumbling.frag
index a7dffc948..46cb1ad37 100644
--- a/src/main/resources/assets/flywheel/flywheel/context/crumbling.frag
+++ b/src/main/resources/assets/flywheel/flywheel/context/crumbling.frag
@@ -12,9 +12,10 @@ vec2 flattenedPos(vec3 pos, vec3 normal) {
pos -= floor(pos) + vec3(0.5);
float sinYRot = -normal.x;
- float sqLength = normal.x * normal.x + normal.z * normal.z;
+ vec2 XZ = normal.xz;
+ float sqLength = dot(XZ, XZ);
if (sqLength > 0) {
- sinYRot /= sqrt(sqLength);
+ sinYRot *= inversesqrt(sqLength);
sinYRot = clamp(sinYRot, -1, 1);
}