diff --git a/luminol-api/paper-patches/features/0006-Pufferfish-SIMD-Utilities.patch b/luminol-api/paper-patches/features/0006-Pufferfish-SIMD-Utilities.patch index 165ea97..db1d3ed 100644 --- a/luminol-api/paper-patches/features/0006-Pufferfish-SIMD-Utilities.patch +++ b/luminol-api/paper-patches/features/0006-Pufferfish-SIMD-Utilities.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Pufferfish SIMD Utilities diff --git a/src/main/java/gg/pufferfish/pufferfish/simd/SIMDChecker.java b/src/main/java/gg/pufferfish/pufferfish/simd/SIMDChecker.java new file mode 100644 -index 0000000000000000000000000000000000000000..f00c008c03e2533f568085838cf13cb9b5b32cd9 +index 0000000000000000000000000000000000000000..856de1331b15542c00e01990f471fa5152722c11 --- /dev/null +++ b/src/main/java/gg/pufferfish/pufferfish/simd/SIMDChecker.java -@@ -0,0 +1,39 @@ +@@ -0,0 +1,35 @@ +package gg.pufferfish.pufferfish.simd; + +import jdk.incubator.vector.FloatVector; @@ -26,24 +26,20 @@ index 0000000000000000000000000000000000000000..f00c008c03e2533f568085838cf13cb9 + @Deprecated + public static boolean canEnable(Logger logger) { + try { -+ if (SIMDDetection.getJavaVersion() < 17 || SIMDDetection.getJavaVersion() > 21) { ++ SIMDDetection.testRun = true; ++ ++ VectorSpecies ISPEC = IntVector.SPECIES_PREFERRED; ++ VectorSpecies FSPEC = FloatVector.SPECIES_PREFERRED; ++ ++ logger.info("Max SIMD vector size on this system is {} bits (int)", ISPEC.vectorBitSize()); ++ logger.info("Max SIMD vector size on this system is " + FSPEC.vectorBitSize() + " bits (float)"); ++ ++ if (ISPEC.elementSize() < 2 || FSPEC.elementSize() < 2) { ++ logger.warn("SIMD is not properly supported on this system!"); + return false; -+ } else { -+ SIMDDetection.testRun = true; -+ -+ VectorSpecies ISPEC = IntVector.SPECIES_PREFERRED; -+ VectorSpecies FSPEC = FloatVector.SPECIES_PREFERRED; -+ -+ logger.info("Max SIMD vector size on this system is {} bits (int)", ISPEC.vectorBitSize()); -+ logger.info("Max SIMD vector size on this system is " + FSPEC.vectorBitSize() + " bits (float)"); -+ -+ if (ISPEC.elementSize() < 2 || FSPEC.elementSize() < 2) { -+ logger.warn("SIMD is not properly supported on this system!"); -+ return false; -+ } -+ -+ return true; + } ++ ++ return true; + } catch (NoClassDefFoundError | Exception ignored) {} // Basically, we don't do anything. This lets us detect if it's not functional and disable it. + return false; + } @@ -51,10 +47,10 @@ index 0000000000000000000000000000000000000000..f00c008c03e2533f568085838cf13cb9 +} diff --git a/src/main/java/gg/pufferfish/pufferfish/simd/SIMDDetection.java b/src/main/java/gg/pufferfish/pufferfish/simd/SIMDDetection.java new file mode 100644 -index 0000000000000000000000000000000000000000..cd953435a6179eaae7c9cc250a791cae26c5567b +index 0000000000000000000000000000000000000000..0a64cd0e88083ac4af6674ad0fb07b771109c737 --- /dev/null +++ b/src/main/java/gg/pufferfish/pufferfish/simd/SIMDDetection.java -@@ -0,0 +1,35 @@ +@@ -0,0 +1,34 @@ +package gg.pufferfish.pufferfish.simd; + +import org.slf4j.Logger; @@ -63,7 +59,6 @@ index 0000000000000000000000000000000000000000..cd953435a6179eaae7c9cc250a791cae +public class SIMDDetection { + + public static boolean isEnabled = false; -+ public static boolean versionLimited = false; + public static boolean testRun = false; + + @Deprecated @@ -90,3 +85,118 @@ index 0000000000000000000000000000000000000000..cd953435a6179eaae7c9cc250a791cae + } + +} +diff --git a/src/main/java/gg/pufferfish/pufferfish/simd/VectorMapPalette.java b/src/main/java/gg/pufferfish/pufferfish/simd/VectorMapPalette.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c26dcaaa2e85882730c854099df80d69eec70f33 +--- /dev/null ++++ b/src/main/java/gg/pufferfish/pufferfish/simd/VectorMapPalette.java +@@ -0,0 +1,84 @@ ++package gg.pufferfish.pufferfish.simd; ++ ++import jdk.incubator.vector.FloatVector; ++import jdk.incubator.vector.IntVector; ++import jdk.incubator.vector.VectorMask; ++import jdk.incubator.vector.VectorSpecies; ++import org.bukkit.map.MapPalette; ++ ++import java.awt.*; ++ ++@Deprecated ++public class VectorMapPalette { ++ ++ private static final VectorSpecies I_SPEC = IntVector.SPECIES_PREFERRED; ++ private static final VectorSpecies F_SPEC = FloatVector.SPECIES_PREFERRED; ++ ++ @Deprecated ++ public static void matchColorVectorized(int[] in, byte[] out) { ++ int speciesLength = I_SPEC.length(); ++ int i; ++ for (i = 0; i < in.length - speciesLength; i += speciesLength) { ++ float[] redsArr = new float[speciesLength]; ++ float[] bluesArr = new float[speciesLength]; ++ float[] greensArr = new float[speciesLength]; ++ int[] alphasArr = new int[speciesLength]; ++ ++ for (int j = 0; j < speciesLength; j++) { ++ alphasArr[j] = (in[i + j] >> 24) & 0xFF; ++ redsArr[j] = (in[i + j] >> 16) & 0xFF; ++ greensArr[j] = (in[i + j] >> 8) & 0xFF; ++ bluesArr[j] = (in[i + j] >> 0) & 0xFF; ++ } ++ ++ IntVector alphas = IntVector.fromArray(I_SPEC, alphasArr, 0); ++ FloatVector reds = FloatVector.fromArray(F_SPEC, redsArr, 0); ++ FloatVector greens = FloatVector.fromArray(F_SPEC, greensArr, 0); ++ FloatVector blues = FloatVector.fromArray(F_SPEC, bluesArr, 0); ++ IntVector resultIndex = IntVector.zero(I_SPEC); ++ VectorMask modificationMask = VectorMask.fromLong(I_SPEC, 0xffffffff); ++ ++ modificationMask = modificationMask.and(alphas.lt(128).not()); ++ FloatVector bestDistances = FloatVector.broadcast(F_SPEC, Float.MAX_VALUE); ++ ++ for (int c = 4; c < MapPalette.colors.length; c++) { ++ // We're using 32-bit floats here because it's 2x faster and nobody will know the difference. ++ // For correctness, the original algorithm uses 64-bit floats instead. Completely unnecessary. ++ FloatVector compReds = FloatVector.broadcast(F_SPEC, MapPalette.colors[c].getRed()); ++ FloatVector compGreens = FloatVector.broadcast(F_SPEC, MapPalette.colors[c].getGreen()); ++ FloatVector compBlues = FloatVector.broadcast(F_SPEC, MapPalette.colors[c].getBlue()); ++ ++ FloatVector rMean = reds.add(compReds).div(2.0f); ++ FloatVector rDiff = reds.sub(compReds); ++ FloatVector gDiff = greens.sub(compGreens); ++ FloatVector bDiff = blues.sub(compBlues); ++ ++ FloatVector weightR = rMean.div(256.0f).add(2); ++ FloatVector weightG = FloatVector.broadcast(F_SPEC, 4.0f); ++ FloatVector weightB = FloatVector.broadcast(F_SPEC, 255.0f).sub(rMean).div(256.0f).add(2.0f); ++ ++ FloatVector distance = weightR.mul(rDiff).mul(rDiff).add(weightG.mul(gDiff).mul(gDiff)).add(weightB.mul(bDiff).mul(bDiff)); ++ ++ // Now we compare to the best distance we've found. ++ // This mask contains a "1" if better, and a "0" otherwise. ++ VectorMask bestDistanceMask = distance.lt(bestDistances); ++ bestDistances = bestDistances.blend(distance, bestDistanceMask); // Update the best distances ++ ++ // Update the result array ++ // We also AND with the modification mask because we don't want to interfere if the alpha value isn't large enough. ++ resultIndex = resultIndex.blend(c, bestDistanceMask.cast(I_SPEC).and(modificationMask)); // Update the results ++ } ++ ++ for (int j = 0; j < speciesLength; j++) { ++ int index = resultIndex.lane(j); ++ out[i + j] = (byte) (index < 128 ? index : -129 + (index - 127)); ++ } ++ } ++ ++ // For the final ones, fall back to the regular method ++ for (; i < in.length; i++) { ++ out[i] = MapPalette.matchColor(new Color(in[i], true)); ++ } ++ } ++ ++} +diff --git a/src/main/java/org/bukkit/map/MapPalette.java b/src/main/java/org/bukkit/map/MapPalette.java +index 6995f9cc08d162e3adcd3a28f6bfa6d329661999..83ea70a16b4090a8c628784f2807cd16e7065103 100644 +--- a/src/main/java/org/bukkit/map/MapPalette.java ++++ b/src/main/java/org/bukkit/map/MapPalette.java +@@ -45,7 +45,7 @@ public final class MapPalette { + } + + @NotNull +- static final Color[] colors = { ++ public static final Color[] colors = { // Luminol - package-private -> public + c(0, 0, 0, 0), c(0, 0, 0, 0), c(0, 0, 0, 0), c(0, 0, 0, 0), + c(89, 125, 39), c(109, 153, 48), c(127, 178, 56), c(67, 94, 29), + c(174, 164, 115), c(213, 201, 140), c(247, 233, 163), c(130, 123, 86), +@@ -216,9 +216,11 @@ public final class MapPalette { + temp.getRGB(0, 0, temp.getWidth(), temp.getHeight(), pixels, 0, temp.getWidth()); + + byte[] result = new byte[temp.getWidth() * temp.getHeight()]; ++ if ((mapColorCache != null && mapColorCache.isCached()) || !gg.pufferfish.pufferfish.simd.SIMDDetection.isEnabled) { // Luminol - Pufferfish - vectorized map color conversion + for (int i = 0; i < pixels.length; i++) { + result[i] = matchColor(new Color(pixels[i], true)); + } ++ } else gg.pufferfish.pufferfish.simd.VectorMapPalette.matchColorVectorized(pixels, result); // Luminol - Pufferfish - vectorized map color conversion + return result; + } + diff --git a/luminol-api/paper-patches/features/0007-Tick-regions-api.patch b/luminol-api/paper-patches/features/0007-Tick-regions-api.patch index 5bfbd2d..0a36040 100644 --- a/luminol-api/paper-patches/features/0007-Tick-regions-api.patch +++ b/luminol-api/paper-patches/features/0007-Tick-regions-api.patch @@ -186,10 +186,10 @@ index 0000000000000000000000000000000000000000..ecde4462b08d701b8bff9f26902f1775 + RegionStats getRegionStats(); +} diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 8784842d14bbbe7dbde181e86782a0955be66924..f998f6f0d3017767aa4dde45a7e8aea5dd36fe99 100644 +index 2729f71ac5525b7669fb7cc8719a75e5ce8d1dfc..9020f0781b399484e2acf0ad139b0b364e1c7a8f 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java -@@ -4407,4 +4407,8 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient +@@ -4409,4 +4409,8 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient } } } diff --git a/luminol-server/paper-patches/files/src/main/java/me/earthme/luminol/config/modules/optimizations/SIMDConfig.java.patch b/luminol-server/paper-patches/files/src/main/java/me/earthme/luminol/config/modules/optimizations/SIMDConfig.java.patch index 2f696dc..722a216 100644 --- a/luminol-server/paper-patches/files/src/main/java/me/earthme/luminol/config/modules/optimizations/SIMDConfig.java.patch +++ b/luminol-server/paper-patches/files/src/main/java/me/earthme/luminol/config/modules/optimizations/SIMDConfig.java.patch @@ -1,6 +1,6 @@ --- /dev/null +++ b/src/main/java/me/earthme/luminol/config/modules/optimizations/SIMDConfig.java -@@ -1,0 +_,53 @@ +@@ -1,0 +_,50 @@ +package me.earthme.luminol.config.modules.optimizations; + +import com.electronwill.nightconfig.core.file.CommentedFileConfig; @@ -37,15 +37,12 @@ + // Attempt to detect vectorization + try { + SIMDDetection.isEnabled = SIMDDetection.canEnable(LOGGER); -+ SIMDDetection.versionLimited = SIMDDetection.getJavaVersion() < 17; + } catch (NoClassDefFoundError | Exception ignored) { + ignored.printStackTrace(); + } + + if (SIMDDetection.isEnabled) { + LOGGER.info("SIMD operations detected as functional. Will replace some operations with faster versions."); -+ } else if (SIMDDetection.versionLimited) { -+ LOGGER.warn("Will not enable SIMD! These optimizations are only safely supported on Java 17+."); + } else { + LOGGER.warn("SIMD operations are available for your server, but are not configured!"); + LOGGER.warn("To enable additional optimizations, add \"--add-modules=jdk.incubator.vector\" to your startup flags, BEFORE the \"-jar\".");