From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: ishland 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..77aed653efa723b17e1943e40202954d730f4b47 --- /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); + } + +} 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..6679e557f4a3c7dbe88c77c605c97ff673425d7e --- /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 speciesPreferred = DoubleVector.SPECIES_PREFERRED; + private static final VectorSpecies speciesGrad = speciesPreferred.length() > 8 ? DoubleVector.SPECIES_512 : speciesPreferred; + private static final VectorSpecies 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])) + ); + } + +} 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 de5ab4040204e63efd4c536106cc83f7b15c90a7..026848b6e3ccf68e5d536f79f1a025f7f8352fe2 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; @@ -88,26 +89,36 @@ public final class ImprovedNoise { return this.p[hash & 255] & 255; } + // Mirai start + /** + * @author ishland + * @reason vectorized perlin + */ private double sampleAndLerp(int sectionX, int sectionY, int sectionZ, double localX, double localY, double localZ, double fadeLocalX) { - int i = this.p(sectionX); - int j = this.p(sectionX + 1); - int k = this.p(i + sectionY); - int l = this.p(i + sectionY + 1); - int m = this.p(j + sectionY); - int n = this.p(j + sectionY + 1); - double d = gradDot(this.p(k + sectionZ), localX, localY, localZ); - double e = gradDot(this.p(m + sectionZ), localX - 1.0D, localY, localZ); - double f = gradDot(this.p(l + sectionZ), localX, localY - 1.0D, localZ); - double g = gradDot(this.p(n + sectionZ), localX - 1.0D, localY - 1.0D, localZ); - double h = gradDot(this.p(k + sectionZ + 1), localX, localY, localZ - 1.0D); - double o = gradDot(this.p(m + sectionZ + 1), localX - 1.0D, localY, localZ - 1.0D); - double p = gradDot(this.p(l + sectionZ + 1), localX, localY - 1.0D, localZ - 1.0D); - double q = gradDot(this.p(n + sectionZ + 1), localX - 1.0D, localY - 1.0D, localZ - 1.0D); - double r = Mth.smoothstep(localX); - double s = Mth.smoothstep(fadeLocalX); - double t = Mth.smoothstep(localZ); - return Mth.lerp3(r, s, t, d, e, f, g, h, o, p, q); + if (wtf.etil.mirai.MiraiConfig.vectorizedPerlinNoise) { + return VectorizedAlgorithms.perlinNoiseVectorized(p, sectionX, sectionY, sectionZ, localX, localY, localZ, fadeLocalX); + } else { + int i = this.p(sectionX); + int j = this.p(sectionX + 1); + int k = this.p(i + sectionY); + int l = this.p(i + sectionY + 1); + int m = this.p(j + sectionY); + int n = this.p(j + sectionY + 1); + double d = gradDot(this.p(k + sectionZ), localX, localY, localZ); + double e = gradDot(this.p(m + sectionZ), localX - 1.0D, localY, localZ); + double f = gradDot(this.p(l + sectionZ), localX, localY - 1.0D, localZ); + double g = gradDot(this.p(n + sectionZ), localX - 1.0D, localY - 1.0D, localZ); + double h = gradDot(this.p(k + sectionZ + 1), localX, localY, localZ - 1.0D); + double o = gradDot(this.p(m + sectionZ + 1), localX - 1.0D, localY, localZ - 1.0D); + double p = gradDot(this.p(l + sectionZ + 1), localX, localY - 1.0D, localZ - 1.0D); + double q = gradDot(this.p(n + sectionZ + 1), localX - 1.0D, localY - 1.0D, localZ - 1.0D); + double r = Mth.smoothstep(localX); + double s = Mth.smoothstep(fadeLocalX); + double t = Mth.smoothstep(localZ); + return Mth.lerp3(r, s, t, d, e, f, g, h, o, p, q); + } } + // Mirai end private double sampleWithDerivative(int sectionX, int sectionY, int sectionZ, double localX, double localY, double localZ, double[] ds) { int i = this.p(sectionX); 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