Files
MiraiMC/patches/server/0098-c2me-vectorizations.vectorize_noise.patch
2022-01-16 19:03:00 +01:00

262 lines
16 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: ishland <ishlandmc@yeah.net>
Date: Tue, 21 Sep 2021 10:37:45 +0200
Subject: [PATCH] c2me: vectorizations.vectorize_noise
Original code by RelativityMC, licensed under MIT
You can find the original code on https://github.com/RelativityMC/C2ME-fabric (Yarn mappings)
diff --git a/src/main/java/com/ishland/c2me/libs/vectorized_algorithms/VectorizedAlgorithms.java b/src/main/java/com/ishland/c2me/libs/vectorized_algorithms/VectorizedAlgorithms.java
new file mode 100644
index 0000000000000000000000000000000000000000..43d1959002295b5f6431e024813b49e30ee7099f
--- /dev/null
+++ b/src/main/java/com/ishland/c2me/libs/vectorized_algorithms/VectorizedAlgorithms.java
@@ -0,0 +1,9 @@
+package com.ishland.c2me.libs.vectorized_algorithms;
+
+public class VectorizedAlgorithms {
+
+ public static double perlinNoiseVectorized(byte[] p, int sectionX, int sectionY, int sectionZ, double localX, double localY, double localZ, double fadeLocalX) {
+ return VectorizedPerlinNoise.sample(p, sectionX, sectionY, sectionZ, localX, localY, localZ, fadeLocalX);
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/ishland/c2me/libs/vectorized_algorithms/VectorizedPerlinNoise.java b/src/main/java/com/ishland/c2me/libs/vectorized_algorithms/VectorizedPerlinNoise.java
new file mode 100644
index 0000000000000000000000000000000000000000..44085c98292654ebb1f6d522b908bd727c761ede
--- /dev/null
+++ b/src/main/java/com/ishland/c2me/libs/vectorized_algorithms/VectorizedPerlinNoise.java
@@ -0,0 +1,115 @@
+package com.ishland.c2me.libs.vectorized_algorithms;
+
+import jdk.incubator.vector.DoubleVector;
+import jdk.incubator.vector.VectorSpecies;
+
+public class VectorizedPerlinNoise {
+
+ protected static final int[][] GRADIENTS = new int[][]{{1, 1, 0}, {-1, 1, 0}, {1, -1, 0}, {-1, -1, 0}, {1, 0, 1}, {-1, 0, 1}, {1, 0, -1}, {-1, 0, -1}, {0, 1, 1}, {0, -1, 1}, {0, 1, -1}, {0, -1, -1}, {1, 1, 0}, {0, -1, 1}, {-1, 1, 0}, {0, -1, -1}};
+ private static final VectorSpecies<Double> speciesPreferred = DoubleVector.SPECIES_PREFERRED;
+ private static final VectorSpecies<Double> speciesGrad = speciesPreferred.length() > 8 ? DoubleVector.SPECIES_512 : speciesPreferred;
+ private static final VectorSpecies<Double> speciesPerlinFade = speciesPreferred.length() > 4 ? DoubleVector.SPECIES_256 : speciesPreferred;
+
+ static {
+ System.out.println("Using vector size of " + speciesGrad.vectorBitSize() + " bits for grad()");
+ System.out.println("Using vector size of " + speciesPerlinFade.vectorBitSize() + " bits for perlinFade()");
+ }
+
+ private static double lerp(double delta, double start, double end) {
+ return start + delta * (end - start);
+ }
+
+ static double sample(byte[] p, int sectionX, int sectionY, int sectionZ, double localX, double localY, double localZ, double fadeLocalX) {
+ int i = p[sectionX & 0xFF] & 255;
+ int j = p[sectionX + 1 & 0xFF] & 255;
+ int k = p[i + sectionY & 0xFF] & 255;
+ int l = p[i + sectionY + 1 & 0xFF] & 255;
+ int m = p[j + sectionY & 0xFF] & 255;
+ int n = p[j + sectionY + 1 & 0xFF] & 255;
+
+ // grad ops
+ double[] gradX = new double[] {
+ GRADIENTS[p[k + sectionZ & 0xFF] & 15][0],
+ GRADIENTS[p[m + sectionZ & 0xFF] & 15][0],
+ GRADIENTS[p[l + sectionZ & 0xFF] & 15][0],
+ GRADIENTS[p[n + sectionZ & 0xFF] & 15][0],
+ GRADIENTS[p[k + sectionZ + 1 & 0xFF] & 15][0],
+ GRADIENTS[p[m + sectionZ + 1 & 0xFF] & 15][0],
+ GRADIENTS[p[l + sectionZ + 1 & 0xFF] & 15][0],
+ GRADIENTS[p[n + sectionZ + 1 & 0xFF] & 15][0],
+ };
+ double[] mulX = new double[] {
+ localX, localX - 1.0, localX, localX - 1.0,
+ localX, localX - 1.0, localX, localX - 1.0,
+ };
+ double[] gradY = new double[] {
+ GRADIENTS[p[k + sectionZ & 0xFF] & 15][1],
+ GRADIENTS[p[m + sectionZ & 0xFF] & 15][1],
+ GRADIENTS[p[l + sectionZ & 0xFF] & 15][1],
+ GRADIENTS[p[n + sectionZ & 0xFF] & 15][1],
+ GRADIENTS[p[k + sectionZ + 1 & 0xFF] & 15][1],
+ GRADIENTS[p[m + sectionZ + 1 & 0xFF] & 15][1],
+ GRADIENTS[p[l + sectionZ + 1 & 0xFF] & 15][1],
+ GRADIENTS[p[n + sectionZ + 1 & 0xFF] & 15][1],
+ };
+ double[] mulY = new double[] {
+ localY, localY, localY - 1.0, localY - 1.0,
+ localY, localY, localY - 1.0, localY - 1.0,
+ };
+ double[] gradZ = new double[] {
+ GRADIENTS[p[k + sectionZ & 0xFF] & 15][2],
+ GRADIENTS[p[m + sectionZ & 0xFF] & 15][2],
+ GRADIENTS[p[l + sectionZ & 0xFF] & 15][2],
+ GRADIENTS[p[n + sectionZ & 0xFF] & 15][2],
+ GRADIENTS[p[k + sectionZ + 1 & 0xFF] & 15][2],
+ GRADIENTS[p[m + sectionZ + 1 & 0xFF] & 15][2],
+ GRADIENTS[p[l + sectionZ + 1 & 0xFF] & 15][2],
+ GRADIENTS[p[n + sectionZ + 1 & 0xFF] & 15][2],
+ };
+ double[] mulZ = new double[] {
+ localZ, localZ, localZ, localZ,
+ localZ - 1.0, localZ - 1.0, localZ - 1.0, localZ - 1.0,
+ };
+
+ double[] gradResArray = new double[8];
+ for (int i1 = 0; i1 < gradX.length; i1 += speciesGrad.length()) {
+ final DoubleVector gradXVector = DoubleVector.fromArray(speciesGrad, gradX, i1);
+ final DoubleVector mulXVector = DoubleVector.fromArray(speciesGrad, mulX, i1);
+ final DoubleVector resX = gradXVector.mul(mulXVector);
+ final DoubleVector gradYVector = DoubleVector.fromArray(speciesGrad, gradY, i1);
+ final DoubleVector mulYVector = DoubleVector.fromArray(speciesGrad, mulY, i1);
+ final DoubleVector resY = gradYVector.mul(mulYVector);
+ final DoubleVector gradZVector = DoubleVector.fromArray(speciesGrad, gradZ, i1);
+ final DoubleVector mulZVector = DoubleVector.fromArray(speciesGrad, mulZ, i1);
+ final DoubleVector resZ = gradZVector.mul(mulZVector);
+ final DoubleVector res = resX.add(resY).add(resZ);
+ res.intoArray(gradResArray, i1);
+ }
+
+ // fade ops
+ // perlinFade(value): value * value * value * (value * (value * 6.0 - 15.0) + 10.0)
+ final double[] fades = new double[]{localX, fadeLocalX, localZ, 0.0};
+ final double[] fadeResArray = new double[4];
+ for (int i1 = 0; i1 < fades.length; i1 += speciesPerlinFade.length()) {
+ final DoubleVector vector = DoubleVector.fromArray(speciesPerlinFade, fades, i1);
+ final DoubleVector res = vector
+ .mul(6.0)
+ .add(-15.0)
+ .mul(vector)
+ .add(10.0)
+ .mul(vector)
+ .mul(vector)
+ .mul(vector);
+ res.intoArray(fadeResArray, i1);
+ }
+
+ // lerp(delta, start, end): start + delta * (end - start)
+
+ return lerp(
+ fadeResArray[2],
+ lerp(fadeResArray[1], lerp(fadeResArray[0], gradResArray[0], gradResArray[1]), lerp(fadeResArray[0], gradResArray[2], gradResArray[3])),
+ lerp(fadeResArray[1], lerp(fadeResArray[0], gradResArray[4], gradResArray[5]), lerp(fadeResArray[0], gradResArray[6], gradResArray[7]))
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/net/minecraft/world/level/levelgen/synth/ImprovedNoise.java b/src/main/java/net/minecraft/world/level/levelgen/synth/ImprovedNoise.java
index cbb044019629796c5b4f0ff708a5a4084932c5f9..53620a833ce92e97866d17f9b7273421d98e2cfd 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/synth/ImprovedNoise.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/synth/ImprovedNoise.java
@@ -1,5 +1,6 @@
package net.minecraft.world.level.levelgen.synth;
+import com.ishland.c2me.libs.vectorized_algorithms.VectorizedAlgorithms; // Mirai
import com.google.common.annotations.VisibleForTesting;
import net.minecraft.util.Mth;
import net.minecraft.world.level.levelgen.RandomSource;
@@ -115,45 +116,49 @@ public final class ImprovedNoise {
* @reason inline math & small optimization: remove frequent type conversions and redundant ops
*/
private double sampleAndLerp(int sectionX, int sectionY, int sectionZ, double localX, double localY, double localZ, double fadeLocalX) {
- int i = this.p[sectionX & 0xFF];
- int j = this.p[sectionX + 1 & 0xFF];
- int k = this.p[i + sectionY & 0xFF];
- int l = this.p[i + sectionY + 1 & 0xFF];
- int m = this.p[j + sectionY & 0xFF];
- int n = this.p[j + sectionY + 1 & 0xFF];
-
- double d = (SIMPLEX_NOISE_GRADIENTS[this.p[k + sectionZ & 0xFF] & 15][0] * localX)
- + (SIMPLEX_NOISE_GRADIENTS[this.p[k + sectionZ & 0xFF] & 15][1] * localY)
- + (SIMPLEX_NOISE_GRADIENTS[this.p[k + sectionZ & 0xFF] & 15][2] * localZ);
- double e = (SIMPLEX_NOISE_GRADIENTS[this.p[m + sectionZ & 0xFF] & 15][0] * (localX - 1.0))
- + (SIMPLEX_NOISE_GRADIENTS[this.p[m + sectionZ & 0xFF] & 15][1] * localY)
- + (SIMPLEX_NOISE_GRADIENTS[this.p[m + sectionZ & 0xFF] & 15][2] * localZ);
- double f = (SIMPLEX_NOISE_GRADIENTS[this.p[l + sectionZ & 0xFF] & 15][0] * localX)
- + (SIMPLEX_NOISE_GRADIENTS[this.p[l + sectionZ & 0xFF] & 15][1] * (localY - 1.0))
- + (SIMPLEX_NOISE_GRADIENTS[this.p[l + sectionZ & 0xFF] & 15][2] * localZ);
- double g = (SIMPLEX_NOISE_GRADIENTS[this.p[n + sectionZ & 0xFF] & 15][0] * (localX - 1.0))
- + (SIMPLEX_NOISE_GRADIENTS[this.p[n + sectionZ & 0xFF] & 15][1] * (localY - 1.0))
- + (SIMPLEX_NOISE_GRADIENTS[this.p[n + sectionZ & 0xFF] & 15][2] * localZ);
- double h = (SIMPLEX_NOISE_GRADIENTS[this.p[k + sectionZ + 1 & 0xFF] & 15][0] * localX)
- + (SIMPLEX_NOISE_GRADIENTS[this.p[k + sectionZ + 1 & 0xFF] & 15][1] * localY)
- + (SIMPLEX_NOISE_GRADIENTS[this.p[k + sectionZ + 1 & 0xFF] & 15][2] * (localZ - 1.0));
- double o = (SIMPLEX_NOISE_GRADIENTS[this.p[m + sectionZ + 1 & 0xFF] & 15][0] * (localX - 1.0))
- + (SIMPLEX_NOISE_GRADIENTS[this.p[m + sectionZ + 1 & 0xFF] & 15][1] * localY)
- + (SIMPLEX_NOISE_GRADIENTS[this.p[m + sectionZ + 1 & 0xFF] & 15][2] * (localZ - 1.0));
- double p = (SIMPLEX_NOISE_GRADIENTS[this.p[l + sectionZ + 1 & 0xFF] & 15][0] * localX)
- + (SIMPLEX_NOISE_GRADIENTS[this.p[l + sectionZ + 1 & 0xFF] & 15][1] * (localY - 1.0))
- + (SIMPLEX_NOISE_GRADIENTS[this.p[l + sectionZ + 1 & 0xFF] & 15][2] * (localZ - 1.0));
- double q = (SIMPLEX_NOISE_GRADIENTS[this.p[n + sectionZ + 1 & 0xFF] & 15][0] * (localX - 1.0))
- + (SIMPLEX_NOISE_GRADIENTS[this.p[n + sectionZ + 1 & 0xFF] & 15][1] * (localY - 1.0))
- + (SIMPLEX_NOISE_GRADIENTS[this.p[n + sectionZ + 1 & 0xFF] & 15][2] * (localZ - 1.0));
-
- double r = localX * localX * localX * (localX * (localX * 6.0 - 15.0) + 10.0);
- double s = fadeLocalX * fadeLocalX * fadeLocalX * (fadeLocalX * (fadeLocalX * 6.0 - 15.0) + 10.0);
- double t = localZ * localZ * localZ * (localZ * (localZ * 6.0 - 15.0) + 10.0);
-
- double v0 = d + r * (e - d) + s * (f + r * (g - f) - (d + r * (e - d)));
- double v1 = h + r * (o - h) + s * (p + r * (q - p) - (h + r * (o - h)));
- return v0 + (t * (v1 - v0));
+ if (wtf.etil.mirai.MiraiConfig.vectorizedPerlinNoise) {
+ return VectorizedAlgorithms.perlinNoiseVectorized(p, sectionX, sectionY, sectionZ, localX, localY, localZ, fadeLocalX);
+ } else {
+ int i = this.p[sectionX & 0xFF];
+ int j = this.p[sectionX + 1 & 0xFF];
+ int k = this.p[i + sectionY & 0xFF];
+ int l = this.p[i + sectionY + 1 & 0xFF];
+ int m = this.p[j + sectionY & 0xFF];
+ int n = this.p[j + sectionY + 1 & 0xFF];
+
+ double d = (SIMPLEX_NOISE_GRADIENTS[this.p[k + sectionZ & 0xFF] & 15][0] * localX)
+ + (SIMPLEX_NOISE_GRADIENTS[this.p[k + sectionZ & 0xFF] & 15][1] * localY)
+ + (SIMPLEX_NOISE_GRADIENTS[this.p[k + sectionZ & 0xFF] & 15][2] * localZ);
+ double e = (SIMPLEX_NOISE_GRADIENTS[this.p[m + sectionZ & 0xFF] & 15][0] * (localX - 1.0))
+ + (SIMPLEX_NOISE_GRADIENTS[this.p[m + sectionZ & 0xFF] & 15][1] * localY)
+ + (SIMPLEX_NOISE_GRADIENTS[this.p[m + sectionZ & 0xFF] & 15][2] * localZ);
+ double f = (SIMPLEX_NOISE_GRADIENTS[this.p[l + sectionZ & 0xFF] & 15][0] * localX)
+ + (SIMPLEX_NOISE_GRADIENTS[this.p[l + sectionZ & 0xFF] & 15][1] * (localY - 1.0))
+ + (SIMPLEX_NOISE_GRADIENTS[this.p[l + sectionZ & 0xFF] & 15][2] * localZ);
+ double g = (SIMPLEX_NOISE_GRADIENTS[this.p[n + sectionZ & 0xFF] & 15][0] * (localX - 1.0))
+ + (SIMPLEX_NOISE_GRADIENTS[this.p[n + sectionZ & 0xFF] & 15][1] * (localY - 1.0))
+ + (SIMPLEX_NOISE_GRADIENTS[this.p[n + sectionZ & 0xFF] & 15][2] * localZ);
+ double h = (SIMPLEX_NOISE_GRADIENTS[this.p[k + sectionZ + 1 & 0xFF] & 15][0] * localX)
+ + (SIMPLEX_NOISE_GRADIENTS[this.p[k + sectionZ + 1 & 0xFF] & 15][1] * localY)
+ + (SIMPLEX_NOISE_GRADIENTS[this.p[k + sectionZ + 1 & 0xFF] & 15][2] * (localZ - 1.0));
+ double o = (SIMPLEX_NOISE_GRADIENTS[this.p[m + sectionZ + 1 & 0xFF] & 15][0] * (localX - 1.0))
+ + (SIMPLEX_NOISE_GRADIENTS[this.p[m + sectionZ + 1 & 0xFF] & 15][1] * localY)
+ + (SIMPLEX_NOISE_GRADIENTS[this.p[m + sectionZ + 1 & 0xFF] & 15][2] * (localZ - 1.0));
+ double p = (SIMPLEX_NOISE_GRADIENTS[this.p[l + sectionZ + 1 & 0xFF] & 15][0] * localX)
+ + (SIMPLEX_NOISE_GRADIENTS[this.p[l + sectionZ + 1 & 0xFF] & 15][1] * (localY - 1.0))
+ + (SIMPLEX_NOISE_GRADIENTS[this.p[l + sectionZ + 1 & 0xFF] & 15][2] * (localZ - 1.0));
+ double q = (SIMPLEX_NOISE_GRADIENTS[this.p[n + sectionZ + 1 & 0xFF] & 15][0] * (localX - 1.0))
+ + (SIMPLEX_NOISE_GRADIENTS[this.p[n + sectionZ + 1 & 0xFF] & 15][1] * (localY - 1.0))
+ + (SIMPLEX_NOISE_GRADIENTS[this.p[n + sectionZ + 1 & 0xFF] & 15][2] * (localZ - 1.0));
+
+ double r = localX * localX * localX * (localX * (localX * 6.0 - 15.0) + 10.0);
+ double s = fadeLocalX * fadeLocalX * fadeLocalX * (fadeLocalX * (fadeLocalX * 6.0 - 15.0) + 10.0);
+ double t = localZ * localZ * localZ * (localZ * (localZ * 6.0 - 15.0) + 10.0);
+
+ double v0 = d + r * (e - d) + s * (f + r * (g - f) - (d + r * (e - d)));
+ double v1 = h + r * (o - h) + s * (p + r * (q - p) - (h + r * (o - h)));
+ return v0 + (t * (v1 - v0));
+ }
}
// Mirai end
diff --git a/src/main/java/wtf/etil/mirai/MiraiConfig.java b/src/main/java/wtf/etil/mirai/MiraiConfig.java
index 1ba057cbd0ec23cd7ef3d3d1c7685f44cfe34eec..90cf922c8df669ac80451d64b376918dece09dc9 100644
--- a/src/main/java/wtf/etil/mirai/MiraiConfig.java
+++ b/src/main/java/wtf/etil/mirai/MiraiConfig.java
@@ -247,4 +247,9 @@ public class MiraiConfig {
riskyMathRoundOpt = getBoolean("use-risky-mathround-opt", riskyMathRoundOpt);
}
+ public static boolean vectorizedPerlinNoise = false;
+ private static void vectorizedNoise() {
+ vectorizedPerlinNoise = getBoolean("use-vectorized-perlin-noise", vectorizedPerlinNoise);
+ }
+
}
\ No newline at end of file