Skip to content

Commit

Permalink
Merge remote-tracking branch 'refs/remotes/origin/1.20.6/stable' into…
Browse files Browse the repository at this point in the history
… 1.21/stable
  • Loading branch information
IMS212 committed Jun 25, 2024
2 parents 19a25aa + 9b937ff commit fe09ed3
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
public class SodiumPreLaunch implements PreLaunchEntrypoint {
@Override
public void onPreLaunch() {
PreLaunchChecks.beforeLWJGLInit();
GraphicsAdapterProbe.findAdapters();
PreLaunchChecks.onGameInit();
Workarounds.init();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class BugChecks {
public static final boolean ISSUE_899 = configureCheck("issue899", true);
public static final boolean ISSUE_1486 = configureCheck("issue1486", true);
public static final boolean ISSUE_2048 = configureCheck("issue2048", true);
public static final boolean ISSUE_2561 = configureCheck("issue2561", true);

private static boolean configureCheck(String name, boolean defaultValue) {
var propertyValue = System.getProperty(getPropertyKey(name), null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,58 @@
import me.jellysquid.mods.sodium.client.util.OsUtils;
import me.jellysquid.mods.sodium.client.util.OsUtils.OperatingSystem;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.Version;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;

/**
* Performs OpenGL driver validation before the game creates an OpenGL context. This runs during the earliest possible
* opportunity at game startup, and uses a custom hardware prober to search for problematic drivers.
*/
public class PreLaunchChecks {
private static final Logger LOGGER = LoggerFactory.getLogger("Sodium-EarlyDriverScanner");

// This string should be determined at compile time, so it can be checked against the runtime version.
private static final String REQUIRED_LWJGL_VERSION = Version.VERSION_MAJOR + "." + Version.VERSION_MINOR + "." + Version.VERSION_REVISION;

private static final String normalMessage = "You must change the LWJGL version in your launcher to continue. This is usually controlled by the settings for a profile or instance in your launcher.";

private static final String prismMessage = "It appears you are using Prism Launcher to start the game. You can likely fix this problem by opening your instance settings and navigating to the Version section in the sidebar.";

public static void beforeLWJGLInit() {
if (BugChecks.ISSUE_2561) {
if (!Version.getVersion().startsWith(REQUIRED_LWJGL_VERSION)) {
String message = normalMessage;

if (System.getProperty("minecraft.launcher.brand", "unknown").equalsIgnoreCase("PrismLauncher")) {
message = prismMessage;
}

showCriticalErrorAndClose("Sodium Renderer - Unsupported LWJGL",
("""
The game failed to start because the currently active LWJGL version is not \
compatible.
Installed version: ###CURRENT_VERSION###
Required version: ###REQUIRED_VERSION###
""" + message)
.replace("###CURRENT_VERSION###", org.lwjgl.Version.getVersion())
.replace("###REQUIRED_VERSION###", REQUIRED_LWJGL_VERSION),
"https://github.com/CaffeineMC/sodium-fabric/wiki/LWJGL-Compatibility");

}
}
}

public static void onGameInit() {
if (BugChecks.ISSUE_899) {
var installedVersion = findIntelDriverMatchingBug899();

if (installedVersion != null) {
showUnsupportedDriverMessageBox(
showCriticalErrorAndClose("Sodium Renderer - Unsupported Driver",
"""
The game failed to start because the currently installed Intel Graphics Driver is not \
compatible.
Expand All @@ -42,7 +78,7 @@ public static void onGameInit() {
var installedVersion = findNvidiaDriverMatchingBug1486();

if (installedVersion != null) {
showUnsupportedDriverMessageBox(
showCriticalErrorAndClose("Sodium Renderer - Unsupported Driver",
"""
The game failed to start because the currently installed NVIDIA Graphics Driver is not \
compatible.
Expand All @@ -58,17 +94,17 @@ public static void onGameInit() {
}
}

private static void showUnsupportedDriverMessageBox(String message, String url) {
private static void showCriticalErrorAndClose(String title, String message, String url) {
// Always print the information to the log file first, just in case we can't show the message box.
LOGGER.error("""
###ERROR_DESCRIPTION###
For more information, please see: ###HELP_URL###"""
.replace("###ERROR_DESCRIPTION###", message)
.replace("###HELP_URL###", url));
.replace("###HELP_URL###", url == null ? "" : url));

// Try to show a graphical message box (if the platform supports it) and shut down the game.
MessageBox.showMessageBox(null, MessageBox.IconType.ERROR, "Sodium Renderer - Unsupported Driver", message, url);
MessageBox.showMessageBox(null, MessageBox.IconType.ERROR, title, message, url);
System.exit(1 /* failure code */);
}

Expand Down Expand Up @@ -130,5 +166,4 @@ private static void showUnsupportedDriverMessageBox(String message, String url)

return null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

public class GraphicsAdapterProbe {
Expand All @@ -21,11 +22,18 @@ public class GraphicsAdapterProbe {
public static void findAdapters() {
LOGGER.info("Searching for graphics cards...");

List<? extends GraphicsAdapterInfo> adapters = switch (OsUtils.getOs()) {
case WIN -> findAdapters$Windows();
case LINUX -> findAdapters$Linux();
default -> null;
};
List<? extends GraphicsAdapterInfo> adapters;

try {
adapters = switch (OsUtils.getOs()) {
case WIN -> findAdapters$Windows();
case LINUX -> findAdapters$Linux();
default -> null;
};
} catch (Exception e) {
LOGGER.error("Failed to find graphics adapters!", e);
return;
}

if (adapters == null) {
// Not supported on this platform
Expand Down Expand Up @@ -90,7 +98,8 @@ public static void findAdapters() {

public static Collection<? extends GraphicsAdapterInfo> getAdapters() {
if (ADAPTERS == null) {
throw new RuntimeException("Graphics adapters not probed yet");
LOGGER.error("Graphics adapters not probed yet; returning an empty list.");
return Collections.emptyList();
}

return ADAPTERS;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ public static GraphicsAdapterVendor fromIcdName(String name) {
// Intel Gen 8 - ig8icd
// Intel Gen 9, 9.5 - ig9icd
// Intel Gen 11 - ig11icd
// Intel Gen 12 - igxelpicd (Xe-LP; integrated) and igxehpicd (Xe-LP; dedicated)
if (name.matches("ig(4|7|75|8|9|11|xelp|xehp)icd(32|64)")) {
// Intel Gen 12 - ig12icd (UHD Graphics, with early drivers)
// igxelpicd (Xe-LP; integrated)
// igxehpicd (Xe-HP; dedicated)
if (name.matches("ig(4|7|75|8|9|11|12|xelp|xehp)icd(32|64)")) {
return INTEL;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@
import org.lwjgl.glfw.GLFWNativeWin32;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil;
import org.lwjgl.util.tinyfd.TinyFileDialogs;

import java.nio.ByteBuffer;
import java.util.Locale;
import java.util.Objects;

public class MessageBox {
Expand All @@ -30,10 +33,11 @@ private interface MessageBoxImpl {
static @Nullable MessageBoxImpl chooseImpl() {
if (OsUtils.getOs() == OsUtils.OperatingSystem.WIN) {
return new WindowsMessageBoxImpl();
} else {
// TODO: Tiny File Dialogs is really bad. We need something better.
//return new TFDMessageBoxImpl();
return null;
}

// TODO: Provide an implementation on other platforms
return null;
}

void showMessageBox(@Nullable Window window,
Expand All @@ -42,6 +46,21 @@ void showMessageBox(@Nullable Window window,
@Nullable String helpUrl);
}

private static class TFDMessageBoxImpl implements MessageBoxImpl {
// This adds information about how to open the help box, since we cannot change the buttons.
private static final String NOTICE = "\n\nFor more information, click OK; otherwise, click Cancel.";

@Override
public void showMessageBox(@Nullable Window window, IconType icon, String title, String description, @Nullable String helpUrl) {
boolean clicked = TinyFileDialogs.tinyfd_messageBox(title, helpUrl == null ? description : description + NOTICE, helpUrl == null ? "ok" : "okcancel", icon.name().toLowerCase(Locale.ROOT), false);

if (clicked && helpUrl != null) {
Util.getOperatingSystem()
.open(helpUrl);
}
}
}

private static class WindowsMessageBoxImpl implements MessageBoxImpl {
@Override
public void showMessageBox(@Nullable Window window,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public class FluidRenderer {
// TODO: allow this to be changed by vertex format
// TODO: move fluid rendering to a separate render pass and control glPolygonOffset and glDepthFunc to fix this properly
private static final float EPSILON = 0.001f;
private static final float ALIGNED_EQUALS_EPSILON = 0.011f;

private final BlockPos.Mutable scratchPos = new BlockPos.Mutable();
private final MutableFloat scratchHeight = new MutableFloat(0);
Expand All @@ -67,16 +68,15 @@ public FluidRenderer(ColorProviderRegistry colorProviderRegistry, LightPipelineP
}

private boolean isFluidOccluded(BlockRenderView world, int x, int y, int z, Direction dir, Fluid fluid) {
BlockPos pos = this.scratchPos.set(x, y, z);
BlockState blockState = world.getBlockState(pos);
BlockPos adjPos = this.scratchPos.set(x + dir.getOffsetX(), y + dir.getOffsetY(), z + dir.getOffsetZ());

if (blockState.isOpaque()) {
return world.getFluidState(adjPos).getFluid().matchesType(fluid) || blockState.isSideSolid(world, pos, dir, SideShapeType.FULL);
var adjPos = this.scratchPos.set(x + dir.getOffsetX(), y + dir.getOffsetY(), z + dir.getOffsetZ());
BlockState blockState = world.getBlockState(adjPos);
if (blockState.getFluidState().getFluid().matchesType(fluid)) {
return true;
}
return world.getFluidState(adjPos).getFluid().matchesType(fluid);
return blockState.isOpaque() && dir != Direction.UP && blockState.isSideSolid(world, adjPos, dir.getOpposite(), SideShapeType.FULL);
}


private boolean isSideExposed(BlockRenderView world, int x, int y, int z, Direction dir, float height) {
BlockPos pos = this.scratchPos.set(x + dir.getOffsetX(), y + dir.getOffsetY(), z + dir.getOffsetZ());
BlockState blockState = world.getBlockState(pos);
Expand All @@ -85,10 +85,7 @@ private boolean isSideExposed(BlockRenderView world, int x, int y, int z, Direct
VoxelShape shape = blockState.getCullingShape(world, pos);

// Hoist these checks to avoid allocating the shape below
if (shape == VoxelShapes.fullCube()) {
// The top face always be inset, so if the shape above is a full cube it can't possibly occlude
return dir == Direction.UP;
} else if (shape.isEmpty()) {
if (shape.isEmpty()) {
return true;
}

Expand All @@ -100,6 +97,10 @@ private boolean isSideExposed(BlockRenderView world, int x, int y, int z, Direct
return true;
}

private static boolean isAlignedEquals(float a, float b) {
return Math.abs(a - b) <= ALIGNED_EQUALS_EPSILON;
}

public void render(WorldSlice world, FluidState fluidState, BlockPos blockPos, BlockPos offset, ChunkBuildBuffers buffers) {
var material = DefaultMaterials.forFluidState(fluidState);
var meshBuilder = buffers.get(material);
Expand Down Expand Up @@ -219,10 +220,30 @@ public void render(WorldSlice world, FluidState fluidState, BlockPos blockPos, B

quad.setSprite(sprite);

setVertex(quad, 0, 0.0f, northWestHeight, 0.0f, u1, v1);
setVertex(quad, 1, 0.0f, southWestHeight, 1.0F, u2, v2);
setVertex(quad, 2, 1.0F, southEastHeight, 1.0F, u3, v3);
setVertex(quad, 3, 1.0F, northEastHeight, 0.0f, u4, v4);

// top surface alignedness is calculated with a more relaxed epsilon
boolean aligned = isAlignedEquals(northEastHeight, northWestHeight)
&& isAlignedEquals(northWestHeight, southEastHeight)
&& isAlignedEquals(southEastHeight, southWestHeight)
&& isAlignedEquals(southWestHeight, northEastHeight);

boolean creaseNorthEastSouthWest = aligned
|| northEastHeight > northWestHeight && northEastHeight > southEastHeight
|| northEastHeight < northWestHeight && northEastHeight < southEastHeight
|| southWestHeight > northWestHeight && southWestHeight > southEastHeight
|| southWestHeight < northWestHeight && southWestHeight < southEastHeight;

if (creaseNorthEastSouthWest) {
setVertex(quad, 1, 0.0f, northWestHeight, 0.0f, u1, v1);
setVertex(quad, 2, 0.0f, southWestHeight, 1.0F, u2, v2);
setVertex(quad, 3, 1.0F, southEastHeight, 1.0F, u3, v3);
setVertex(quad, 0, 1.0F, northEastHeight, 0.0f, u4, v4);
} else {
setVertex(quad, 0, 0.0f, northWestHeight, 0.0f, u1, v1);
setVertex(quad, 1, 0.0f, southWestHeight, 1.0F, u2, v2);
setVertex(quad, 2, 1.0F, southEastHeight, 1.0F, u3, v3);
setVertex(quad, 3, 1.0F, northEastHeight, 0.0f, u4, v4);
}

this.updateQuad(quad, world, blockPos, lighter, Direction.UP, 1.0F, colorProvider, fluidState);
this.writeQuad(meshBuilder, material, offset, quad, facing, false);
Expand All @@ -232,7 +253,6 @@ public void render(WorldSlice world, FluidState fluidState, BlockPos blockPos, B
ModelQuadFacing.NEG_Y, true);

}

}

if (!sfDown) {
Expand Down Expand Up @@ -367,7 +387,7 @@ private ColorProvider<FluidState> getColorProvider(Fluid fluid, FluidRenderHandl
if (override != null) {
return override;
}

return DefaultColorProviders.adapt(handler);
}

Expand Down Expand Up @@ -401,7 +421,7 @@ private void writeQuad(ChunkModelBuilder builder, Material material, BlockPos of
var vertices = this.vertices;

for (int i = 0; i < 4; i++) {
var out = vertices[flip ? 3 - i : i];
var out = vertices[flip ? (3 - i + 1) & 0b11 : i];
out.x = offset.getX() + quad.getX(i);
out.y = offset.getY() + quad.getY(i);
out.z = offset.getZ() + quad.getZ(i);
Expand Down

0 comments on commit fe09ed3

Please sign in to comment.