diff --git a/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/AdvancedShadowCullingFrustum.java b/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/AdvancedShadowCullingFrustum.java index 6e6ce6ce58..8d7e1117b2 100644 --- a/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/AdvancedShadowCullingFrustum.java +++ b/common/src/main/java/net/irisshaders/iris/shadows/frustum/advanced/AdvancedShadowCullingFrustum.java @@ -1,5 +1,7 @@ package net.irisshaders.iris.shadows.frustum.advanced; +import com.sun.management.HotSpotDiagnosticMXBean; +import com.sun.management.VMOption; import net.caffeinemc.mods.sodium.client.render.viewport.Viewport; import net.caffeinemc.mods.sodium.client.render.viewport.ViewportProvider; import net.irisshaders.iris.shadows.frustum.BoxCuller; @@ -10,6 +12,8 @@ import org.joml.Vector3f; import org.joml.Vector4f; +import java.lang.management.ManagementFactory; + /** * A Frustum implementation that derives a tightly-fitted shadow pass frustum based on the player's camera frustum and * an assumption that the shadow map will only be sampled for the purposes of direct shadow casting, volumetric lighting, @@ -312,6 +316,25 @@ protected int isVisible(double minX, double minY, double minZ, double maxX, doub return this.checkCornerVisibility(f, g, h, i, j, k); } + private static final boolean FMA_SUPPORT; + + static { + // Automatically enable `joml.useMathFma` system property if JVM UseFMA is enabled. + // The JVM will automatically enable the UseFMA vm option if the cpu supports it. + // Thanks to kunzite for making me aware of this. + final HotSpotDiagnosticMXBean hotSpotDiagnostic = ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class); + if (hotSpotDiagnostic == null) { + FMA_SUPPORT = false; + } else { + final VMOption useFMAVMOption = hotSpotDiagnostic.getVMOption("UseFMA"); + FMA_SUPPORT = Boolean.parseBoolean(useFMAVMOption.getValue()); + } + } + + private static float safeFMA(float a, float b, float c) { + return a * b + c; + } + /** * Checks corner visibility. * @@ -330,13 +353,19 @@ protected int checkCornerVisibility(float minX, float minY, float minZ, float ma // Check if plane is inside or intersecting. // This is ported from JOML's FrustumIntersection. - float outsideBoundX = (plane.x() < 0) ? minX : maxX; - float outsideBoundY = (plane.y() < 0) ? minY : maxY; - float outsideBoundZ = (plane.z() < 0) ? minZ : maxZ; + float outsideBoundX = (plane.x < 0) ? minX : maxX; + float outsideBoundY = (plane.y < 0) ? minY : maxY; + float outsideBoundZ = (plane.z < 0) ? minZ : maxZ; // Use Math.fma for the dot product calculation to get vectorization (sorry old Intel users) - if (Math.fma(plane.x(), outsideBoundX, Math.fma(plane.y(), outsideBoundY, plane.z() * outsideBoundZ)) < -plane.w()) { - return 0; + if (FMA_SUPPORT) { + if (Math.fma(plane.x, outsideBoundX, Math.fma(plane.y, outsideBoundY, plane.z * outsideBoundZ)) < -plane.w) { + return 0; + } + } else { + if (safeFMA(plane.x, outsideBoundX, safeFMA(plane.y, outsideBoundY, plane.z * outsideBoundZ)) < -plane.w) { + return 0; + } } }