Make SIMD actually work
This commit is contained in:
@@ -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<Integer> ISPEC = IntVector.SPECIES_PREFERRED;
|
||||
+ VectorSpecies<Float> 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<Integer> ISPEC = IntVector.SPECIES_PREFERRED;
|
||||
+ VectorSpecies<Float> 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<Integer> I_SPEC = IntVector.SPECIES_PREFERRED;
|
||||
+ private static final VectorSpecies<Float> 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<Integer> 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<Float> 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user