diff --git a/LICENSE.md b/LICENSE.md index ecc0bf77c..518a2732c 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,4 +1,4 @@ -Copyright (c) 2021 Jozufozu +Copyright (c) 2021-2023 Jozufozu Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/build.gradle b/build.gradle index 55a816298..d16ee74b7 100644 --- a/build.gradle +++ b/build.gradle @@ -146,8 +146,8 @@ dependencies { // switch to implementation for debugging compileOnly fg.deobf("maven.modrinth:starlight-forge:1.0.2+1.18.2") - compileOnly fg.deobf("maven.modrinth:rubidium:0.5.3a") - compileOnly fg.deobf("maven.modrinth:oculus:1.18.2-1.2.5a") + compileOnly fg.deobf("maven.modrinth:rubidium:0.5.6") + compileOnly fg.deobf("maven.modrinth:oculus:1.18.2-1.5.2") // https://discord.com/channels/313125603924639766/725850371834118214/910619168821354497 // Prevent Mixin annotation processor from getting into IntelliJ's annotation processor settings diff --git a/gradle.properties b/gradle.properties index bcf602c21..26c1ac393 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,12 +5,12 @@ org.gradle.daemon = false mod_version = 1.0.0-alpha artifact_minecraft_version = 1.18.2 -minecraft_version = 1.18.2 -forge_version = 40.1.68 +minecraft_version=1.18.2 +forge_version=40.2.4 # build dependency versions -forgegradle_version = 5.1.53 -mixingradle_version = 0.7-SNAPSHOT +forgegradle_version=5.1.+ +mixingradle_version=0.7-SNAPSHOT mixin_version = 0.8.5 librarian_version = 1.+ cursegradle_version = 1.4.0 diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/batching/TransformCall.java b/src/main/java/com/jozufozu/flywheel/backend/engine/batching/TransformCall.java index 25fb8c94b..63b5e91a1 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/batching/TransformCall.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/batching/TransformCall.java @@ -20,11 +20,7 @@ import com.mojang.math.Matrix4f; public class TransformCall { private final CPUInstancer instancer; - private final Material material; - private final BatchedMeshPool.BufferedMesh mesh; - private final int meshVertexCount; - private final int meshByteSize; private final InstanceVertexTransformer instanceVertexTransformer; private final MaterialVertexTransformer materialVertexTransformer; private final InstanceBoundingSphereTransformer boundingSphereTransformer; @@ -34,15 +30,12 @@ public class TransformCall { public TransformCall(CPUInstancer instancer, Material material, BatchedMeshPool.BufferedMesh mesh) { this.instancer = instancer; - this.material = material; - this.mesh = mesh; instanceVertexTransformer = instancer.type.getVertexTransformer(); boundingSphereTransformer = instancer.type.getBoundingSphereTransformer(); materialVertexTransformer = material.getVertexTransformer(); meshVertexCount = mesh.getVertexCount(); - meshByteSize = mesh.size(); boundingSphere = mesh.mesh.getBoundingSphere(); drawPlan = RunOnAllWithContextPlan.of(instancer::getAll, (instance, ctx) -> { diff --git a/src/main/java/com/jozufozu/flywheel/backend/task/ParallelTaskExecutor.java b/src/main/java/com/jozufozu/flywheel/backend/task/ParallelTaskExecutor.java index 0590d301a..f243f2149 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/task/ParallelTaskExecutor.java +++ b/src/main/java/com/jozufozu/flywheel/backend/task/ParallelTaskExecutor.java @@ -9,11 +9,11 @@ import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicBoolean; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.api.task.TaskExecutor; +import com.jozufozu.flywheel.lib.task.ThreadGroupNotifier; import com.jozufozu.flywheel.lib.task.WaitGroup; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.logging.LogUtils; @@ -37,7 +37,7 @@ public class ParallelTaskExecutor implements TaskExecutor { private final Deque taskQueue = new ConcurrentLinkedDeque<>(); private final Queue mainThreadQueue = new ConcurrentLinkedQueue<>(); - private final Object taskNotifier = new Object(); + private final ThreadGroupNotifier taskNotifier = new ThreadGroupNotifier(); private final WaitGroup waitGroup = new WaitGroup(); public ParallelTaskExecutor(String name) { @@ -114,9 +114,7 @@ public class ParallelTaskExecutor implements TaskExecutor { waitGroup.add(); taskQueue.add(task); - synchronized (taskNotifier) { - taskNotifier.notifyAll(); - } + taskNotifier.postNotification(); } @Override @@ -148,8 +146,8 @@ public class ParallelTaskExecutor implements TaskExecutor { } else { // then wait for the other threads to finish. waitGroup.await(); - // at this point there will be no more tasks in the queue, but - // one of the worker threads may have submitted a main thread task. + // at this point we know taskQueue is empty, + // but one of the worker threads may have submitted a main thread task. if (mainThreadQueue.isEmpty()) { // if they didn't, we're done. break; @@ -170,23 +168,6 @@ public class ParallelTaskExecutor implements TaskExecutor { mainThreadQueue.clear(); } - @Nullable - private Runnable getNextTask() { - Runnable task = taskQueue.pollFirst(); - - if (task == null) { - synchronized (taskNotifier) { - try { - taskNotifier.wait(); - } catch (InterruptedException e) { - // - } - } - } - - return task; - } - private void processTask(Runnable task) { try { task.run(); @@ -226,9 +207,11 @@ public class ParallelTaskExecutor implements TaskExecutor { public void run() { // Run until the executor shuts down while (ParallelTaskExecutor.this.running.get()) { - Runnable task = getNextTask(); + Runnable task = taskQueue.pollFirst(); if (task == null) { + // Nothing to do, time to sleep. + taskNotifier.awaitNotification(); continue; } diff --git a/src/main/java/com/jozufozu/flywheel/lib/math/MatrixUtil.java b/src/main/java/com/jozufozu/flywheel/lib/math/MatrixUtil.java index 9d42df9b6..7f495936e 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/math/MatrixUtil.java +++ b/src/main/java/com/jozufozu/flywheel/lib/math/MatrixUtil.java @@ -1,7 +1,10 @@ package com.jozufozu.flywheel.lib.math; +import static org.joml.Math.fma; + import java.nio.ByteBuffer; +import org.joml.Math; import org.lwjgl.system.MemoryUtil; import com.jozufozu.flywheel.mixin.matrix.Matrix3fAccessor; @@ -12,32 +15,32 @@ import com.mojang.math.Matrix4f; public final class MatrixUtil { public static float transformPositionX(Matrix4f matrix, float x, float y, float z) { Matrix4fAccessor m = (Matrix4fAccessor) (Object) matrix; - return (m.flywheel$m00() * x) + (m.flywheel$m01() * y) + (m.flywheel$m02() * z) + m.flywheel$m03(); + return fma(m.flywheel$m00(), x, fma(m.flywheel$m01(), y, fma(m.flywheel$m02(), z, m.flywheel$m03()))); } public static float transformPositionY(Matrix4f matrix, float x, float y, float z) { Matrix4fAccessor m = (Matrix4fAccessor) (Object) matrix; - return (m.flywheel$m10() * x) + (m.flywheel$m11() * y) + (m.flywheel$m12() * z) + m.flywheel$m13(); + return fma(m.flywheel$m10(), x, fma(m.flywheel$m11(), y, fma(m.flywheel$m12(), z, m.flywheel$m13()))); } public static float transformPositionZ(Matrix4f matrix, float x, float y, float z) { Matrix4fAccessor m = (Matrix4fAccessor) (Object) matrix; - return (m.flywheel$m20() * x) + (m.flywheel$m21() * y) + (m.flywheel$m22() * z) + m.flywheel$m23(); + return fma(m.flywheel$m20(), x, fma(m.flywheel$m21(), y, fma(m.flywheel$m22(), z, m.flywheel$m23()))); } public static float transformNormalX(Matrix3f matrix, float x, float y, float z) { Matrix3fAccessor m = (Matrix3fAccessor) (Object) matrix; - return (m.flywheel$m00() * x) + (m.flywheel$m01() * y) + (m.flywheel$m02() * z); + return fma(m.flywheel$m00(), x, fma(m.flywheel$m01(), y, m.flywheel$m02() * z)); } public static float transformNormalY(Matrix3f matrix, float x, float y, float z) { Matrix3fAccessor m = (Matrix3fAccessor) (Object) matrix; - return (m.flywheel$m10() * x) + (m.flywheel$m11() * y) + (m.flywheel$m12() * z); + return fma(m.flywheel$m10(), x, fma(m.flywheel$m11(), y, m.flywheel$m12() * z)); } public static float transformNormalZ(Matrix3f matrix, float x, float y, float z) { Matrix3fAccessor m = (Matrix3fAccessor) (Object) matrix; - return (m.flywheel$m20() * x) + (m.flywheel$m21() * y) + (m.flywheel$m22() * z); + return fma(m.flywheel$m20(), x, fma(m.flywheel$m21(), y, m.flywheel$m22() * z)); } public static void write(Matrix4f matrix, ByteBuffer buf) { diff --git a/src/main/java/com/jozufozu/flywheel/lib/task/ThreadGroupNotifier.java b/src/main/java/com/jozufozu/flywheel/lib/task/ThreadGroupNotifier.java new file mode 100644 index 000000000..b07b52662 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/lib/task/ThreadGroupNotifier.java @@ -0,0 +1,19 @@ +package com.jozufozu.flywheel.lib.task; + +/** + * Thin wrapper around Java's built-in object synchronization primitives. + */ +public class ThreadGroupNotifier { + + public synchronized void awaitNotification() { + try { + this.wait(); + } catch (InterruptedException e) { + // we don't care if we're interrupted, just continue. + } + } + + public synchronized void postNotification() { + this.notifyAll(); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/lib/task/WaitGroup.java b/src/main/java/com/jozufozu/flywheel/lib/task/WaitGroup.java index 923aae154..92411bac2 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/task/WaitGroup.java +++ b/src/main/java/com/jozufozu/flywheel/lib/task/WaitGroup.java @@ -4,6 +4,7 @@ import java.util.concurrent.atomic.AtomicInteger; import org.slf4j.Logger; +import com.google.common.base.Preconditions; import com.mojang.logging.LogUtils; public class WaitGroup { @@ -16,6 +17,7 @@ public class WaitGroup { } public void add(int i) { + Preconditions.checkArgument(i >= 0, "Cannot add a negative number of tasks to a WaitGroup!"); if (i == 0) { return; } @@ -31,17 +33,9 @@ public class WaitGroup { public void await() { // TODO: comprehensive performance tracking for tasks - long start = System.nanoTime(); - int count = 0; while (counter.get() > 0) { // spin in place to avoid sleeping the main thread - count++; - } - long end = System.nanoTime(); - long elapsed = end - start; - - if (elapsed > 1000000) { // > 1ms - // LOGGER.debug("Waited " + StringUtil.formatTime(elapsed) + ", looped " + count + " times"); + Thread.onSpinWait(); } } diff --git a/src/main/java/com/jozufozu/flywheel/lib/vertex/VertexTransformations.java b/src/main/java/com/jozufozu/flywheel/lib/vertex/VertexTransformations.java index 4e37aff40..9842fa430 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/vertex/VertexTransformations.java +++ b/src/main/java/com/jozufozu/flywheel/lib/vertex/VertexTransformations.java @@ -1,5 +1,8 @@ package com.jozufozu.flywheel.lib.vertex; +import static org.joml.Math.fma; +import static org.joml.Math.invsqrt; + import com.jozufozu.flywheel.api.vertex.MutableVertexList; import com.jozufozu.flywheel.lib.math.MatrixUtil; import com.mojang.math.Matrix3f; @@ -22,9 +25,9 @@ public final class VertexTransformations { float tnx = MatrixUtil.transformNormalX(matrix, nx, ny, nz); float tny = MatrixUtil.transformNormalY(matrix, nx, ny, nz); float tnz = MatrixUtil.transformNormalZ(matrix, nx, ny, nz); - float sqrLength = tnx * tnx + tny * tny + tnz * tnz; + float sqrLength = fma(tnx, tnx, fma(tny, tny, tnz * tnz)); if (sqrLength != 0) { - float f = 1 / (float) Math.sqrt(sqrLength); + float f = invsqrt(sqrLength); tnx *= f; tny *= f; tnz *= f; diff --git a/src/test/java/com/jozufozu/flywheel/lib/task/WaitGroupTest.java b/src/test/java/com/jozufozu/flywheel/lib/task/WaitGroupTest.java index 779170299..4f5618a31 100644 --- a/src/test/java/com/jozufozu/flywheel/lib/task/WaitGroupTest.java +++ b/src/test/java/com/jozufozu/flywheel/lib/task/WaitGroupTest.java @@ -1,6 +1,7 @@ package com.jozufozu.flywheel.lib.task; -import org.junit.jupiter.api.Assertions; +import static org.junit.jupiter.api.Assertions.assertThrows; + import org.junit.jupiter.api.Test; public class WaitGroupTest { @@ -9,6 +10,12 @@ public class WaitGroupTest { WaitGroup wg = new WaitGroup(); wg.add(); wg.done(); - Assertions.assertThrows(IllegalStateException.class, wg::done); + assertThrows(IllegalStateException.class, wg::done); + } + + @Test + public void testAddNegative() { + WaitGroup wg = new WaitGroup(); + assertThrows(IllegalArgumentException.class, () -> wg.add(-1)); } }