Skip to content

Commit

Permalink
Merge branch 'dev' into gfni
Browse files Browse the repository at this point in the history
  • Loading branch information
douira committed Nov 16, 2023
2 parents cbee812 + 1c7ec04 commit 88b6c09
Show file tree
Hide file tree
Showing 36 changed files with 759 additions and 28 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ them up to date. For many Linux distributions, these dependencies will be standa
repositories.

- OpenJDK 17
- We recommend using the [Eclipse Termurin](https://adoptium.net/) distribution, as it's known to be high quality
- We recommend using the [Eclipse Temurin](https://adoptium.net/) distribution, as it's known to be high quality
and to work without issues.
- Gradle 8.2.1 (optional)
- The [Gradle wrapper](https://docs.gradle.org/current/userguide/gradle_wrapper.html#sec:using_wrapper) is provided
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,8 @@ private static void renderBlockEntity(MatrixStack matrices,
matrices.pop();
}

// the volume of a section multiplied by the number of sections to be checked at most
private static final double MAX_ENTITY_CHECK_VOLUME = 16 * 16 * 16 * 15;

/**
* Returns whether or not the entity intersects with any visible chunks in the graph.
Expand All @@ -400,6 +402,13 @@ public boolean isEntityVisible(Entity entity) {

Box box = entity.getVisibilityBoundingBox();

// bail on very large entities to avoid checking many sections
double entityVolume = (box.maxX - box.minX) * (box.maxY - box.minY) * (box.maxZ - box.minZ);
if (entityVolume > MAX_ENTITY_CHECK_VOLUME) {
// TODO: do a frustum check instead, even large entities aren't visible if they're outside the frustum
return true;
}

return this.isBoxVisible(box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,7 @@ public RenderRegion getRegion() {
return this.region;
}

public int size() {
return this.size;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,31 @@ public void add(RenderSection section) {
RenderRegion region = section.getRegion();
ChunkRenderList list = region.getRenderList();

// Even if a section does not have render objects, we must ensure the render list is initialized and put
// into the sorted queue of lists, so that we maintain the correct order of draw calls.
if (list.getLastVisibleFrame() != this.frame) {
list.reset(this.frame);

this.lists.add(list);
}

list.add(section);
// Only add the section to the render list if it actually contains render objects
if (section.getFlags() != 0) {
list.add(section);
}
}

public SortedRenderLists build() {
return new SortedRenderLists(this.lists);
var filtered = new ObjectArrayList<ChunkRenderList>(this.lists.size());

// Filter any empty render lists
for (var list : this.lists) {
if (list.size() > 0) {
filtered.add(list);
}
}

return new SortedRenderLists(filtered);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@ public VisibleChunkCollector(int frame) {

@Override
public void accept(RenderSection section) {
if (section.getFlags() != 0) {
this.sortedRenderLists.add(section);
}
this.sortedRenderLists.add(section);

this.addToRebuildLists(section);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,13 @@ private static int nearestToZero(int min, int max) {
return clamped;
}

// The bounding box of a chunk section must be large enough to contain all possible geometry within it. Block models
// can extend outside a block volume by +/- 1.0 blocks on all axis. Additionally, we make use of a small epsilon
// to deal with floating point imprecision during a frustum check (see GH#2132).
private static final float CHUNK_SECTION_SIZE = 8.0f /* chunk bounds */ + 1.0f /* maximum model extent */ + 0.125f /* epsilon */;

public static boolean isOutsideFrustum(Viewport viewport, RenderSection section) {
return !viewport.isBoxVisible(section.getCenterX(), section.getCenterY(), section.getCenterZ(), 8.0f);
return !viewport.isBoxVisible(section.getCenterX(), section.getCenterY(), section.getCenterZ(), CHUNK_SECTION_SIZE);
}

private void init(Consumer<RenderSection> visitor,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,15 @@ public void render(@Nullable ClientWorld world, ClientPlayerEntity player, Matri
return;
}

Vec3d color = world.getCloudsColor(tickDelta);

float cloudHeight = world.getDimensionEffects().getCloudsHeight();

// Vanilla uses NaN height as a way to disable cloud rendering
if (Float.isNaN(cloudHeight)) {
return;
}

Vec3d color = world.getCloudsColor(tickDelta);

double cloudTime = (ticks + tickDelta) * 0.03F;
double cloudCenterX = (cameraX + cloudTime);
double cloudCenterZ = (cameraZ) + 0.33D;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package me.jellysquid.mods.sodium.client.render.util;

import java.util.concurrent.ConcurrentLinkedDeque;

public class DeferredRenderTask {
private static final ConcurrentLinkedDeque<Runnable> queue = new ConcurrentLinkedDeque<>();

/**
* Schedules a render task to be executed on the main render thread as soon as possible. This is often at the
* start of the next frame.
* @param runnable The task to be executed on the render thread
*/
public static void schedule(Runnable runnable) {
queue.add(runnable);
}

/**
* Executes all currently pending render tasks. This should only be called from the main render thread!
*/
public static void runAll() {
RenderAsserts.validateCurrentThread();

Runnable runnable;

while ((runnable = queue.poll()) != null) {
try {
runnable.run();
} catch (Throwable throwable) {
throw new RuntimeException("Failed to execute deferred render task", throwable);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package me.jellysquid.mods.sodium.client.render.util;

import com.mojang.blaze3d.systems.RenderSystem;

public class RenderAsserts {
/**
* Checks that the thread calling this function is the main render thread. This is useful for ensuring that OpenGL
* APIs are not accessed from off-thread incorrectly, which is known to cause severe issues.
*
* @throws IllegalStateException If the current thread is not the main render thread
* @return Always true, since an exception is thrown otherwise
*/
public static boolean validateCurrentThread() {
if (!RenderSystem.isOnRenderThread()) {
throw new IllegalStateException("Accessing OpenGL functions from outside the main render thread is not supported when using Sodium");
}

return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package me.jellysquid.mods.sodium.client.util.workarounds;

import me.jellysquid.mods.sodium.client.gui.console.Console;
import me.jellysquid.mods.sodium.client.gui.console.message.MessageLevel;
import net.minecraft.resource.ResourceManager;
import net.minecraft.resource.ResourceType;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class InGameChecks {

private static final Logger LOGGER = LoggerFactory.getLogger("Sodium-InGameChecks");
private static final List<String> VSH_FSH_BLACKLIST = Arrays.asList(
"rendertype_solid.vsh", "rendertype_solid.fsh",
"rendertype_cutout_mipped.vsh", "rendertype_cutout_mipped.fsh",
"rendertype_cutout.vsh", "rendertype_cutout.fsh",
"rendertype_translucent.vsh", "rendertype_translucent.fsh",
"rendertype_tripwire.vsh", "rendertype_tripwire.fsh"
);
private static final List<String> GLSL_BLACKLIST = Arrays.asList(
"light.glsl",
"fog.glsl"
);

/**
* <a href="https://github.com/CaffeineMC/sodium-fabric/issues/1569">#1569</a>
* Iterate through all active resource packs, and detect resource packs which contain files matching the blacklist.
* An error message is shown for resource packs which replace terrain core shaders.
* A warning is shown for resource packs which replace the default light.glsl and fog.glsl shaders.
* Detailed information on shader files replaced by resource packs is printed in the client log.
*/
public static void checkIfCoreShaderLoaded(ResourceManager manager) {
HashMap<String, MessageLevel> detectedResourcePacks = new HashMap<>();
var customResourcePacks = manager.streamResourcePacks();

customResourcePacks.forEach(resourcePack -> {
// Omit 'vanilla' and 'fabric' resource packs
if (!resourcePack.getName().equals("vanilla") && !resourcePack.getName().equals("fabric")) {
var resourcePackName = resourcePack.getName();

resourcePack.findResources(ResourceType.CLIENT_RESOURCES, Identifier.DEFAULT_NAMESPACE, "shaders", (path, ignored) -> {
// Trim full shader file path to only contain the filename
var shaderName = path.getPath().substring(path.getPath().lastIndexOf('/') + 1);
if (VSH_FSH_BLACKLIST.contains(shaderName)) {

if (!detectedResourcePacks.containsKey(resourcePackName)) {
detectedResourcePacks.put(resourcePackName, MessageLevel.SEVERE);
} else if (detectedResourcePacks.get(resourcePackName) == MessageLevel.WARN) {
detectedResourcePacks.replace(resourcePackName, MessageLevel.SEVERE);
}

LOGGER.error("Resource pack '" + resourcePackName + "' replaces core shader '" + shaderName + "'");
}

if (GLSL_BLACKLIST.contains(shaderName)) {

if (!detectedResourcePacks.containsKey(resourcePackName)) {
detectedResourcePacks.put(resourcePackName, MessageLevel.WARN);
}

LOGGER.warn("Resource pack '" + resourcePackName + "' replaces shader '" + shaderName + "'");

}
});
}
});

if (detectedResourcePacks.containsValue(MessageLevel.SEVERE)) {
showConsoleMessage(Text.translatable("sodium.console.core_shaders_error"), MessageLevel.SEVERE);

for (Map.Entry<String, MessageLevel> entry : detectedResourcePacks.entrySet()) {

if (entry.getValue() == MessageLevel.SEVERE) {
// Omit 'file/' prefix for the in-game message
var message = entry.getKey().startsWith("file/") ? entry.getKey().substring(5) : entry.getKey();
showConsoleMessage(Text.literal(message), MessageLevel.SEVERE);
}
}
}

if (detectedResourcePacks.containsValue(MessageLevel.WARN)) {
showConsoleMessage(Text.translatable("sodium.console.core_shaders_warn"), MessageLevel.WARN);

for (Map.Entry<String, MessageLevel> entry : detectedResourcePacks.entrySet()) {

if (entry.getValue() == MessageLevel.WARN) {
// Omit 'file/' prefix for the in-game message
var message = entry.getKey().startsWith("file/") ? entry.getKey().substring(5) : entry.getKey();
showConsoleMessage(Text.literal(message), MessageLevel.WARN);
}
}
}

if (!detectedResourcePacks.isEmpty()) {
showConsoleMessage(Text.translatable("sodium.console.core_shaders_info"), MessageLevel.INFO);
}
}

private static void showConsoleMessage(MutableText message, MessageLevel messageLevel) {
Console.instance().logMessage(messageLevel, message, 20.0);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import me.jellysquid.mods.sodium.client.gui.console.Console;
import me.jellysquid.mods.sodium.client.gui.console.message.MessageLevel;
import me.jellysquid.mods.sodium.client.util.workarounds.driver.nvidia.NvidiaGLContextInfo;
import me.jellysquid.mods.sodium.client.util.workarounds.platform.windows.WindowsModuleChecks;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.minecraft.util.Util;
Expand All @@ -23,6 +24,9 @@ public static void checkContext() {
"likely cause severe performance issues, graphical issues, and crashes when used with Sodium. This " +
"configuration is not supported -- you are on your own!");
}

// We should also check that nothing problematic has been injected into the process.
WindowsModuleChecks.checkModules();
}

private static void checkContextImplementation() {
Expand Down Expand Up @@ -123,5 +127,4 @@ private static boolean isUsingPojavLauncher() {
private static boolean isKnownAndroidPathFragment(String path) {
return path.matches("/data/user/[0-9]+/net\\.kdt\\.pojavlaunch");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,19 @@ public class PreLaunchChecks {
private static final Logger LOGGER = LoggerFactory.getLogger("Sodium-PrelaunchChecks");

public static void checkDrivers() {
boolean check = Boolean.parseBoolean(System.getProperty("sodium.driver.check", "true"));

if (!check) {
return;
}

if (isBrokenIntelGen7GraphicsDriver()) {
if (Boolean.parseBoolean(System.getProperty("sodium.checks.win32.intelGen7", "true")) && isBrokenIntelGen7GraphicsDriver()) {
LOGGER.error("------------------------------------------------------------------------------------------------------------");
LOGGER.error("READ ME! You appear to be using an Intel graphics card with unsupported drivers!");
LOGGER.error(" * Certain graphics cards (such as the Intel HD 2500/4000) currently ship with broken graphics drivers " +
"through Windows Update.");
LOGGER.error(" * You need to update your graphics drivers to fix this problem. More instructions can be found here:");
LOGGER.error(" https://github.com/CaffeineMC/sodium-fabric/issues/899");
LOGGER.error(" https://github.com/CaffeineMC/sodium-fabric/issues/899");
LOGGER.error(" * HINT: You cannot use Windows Update or the Intel Graphics Control Panel to install the updated graphics " +
"driver, as they incorrectly report that the driver is 'already up to date'.");

LOGGER.error(" * HINT: If you believe this is an error, then you can force the game to start anyways by adding the " +
"following JVM argument.");
LOGGER.error(" -Dsodium.driver.check=false");
LOGGER.error(" -Dsodium.checks.win32.intelGen7" + "=false");
LOGGER.error(" * NOTE: We will not provide support for any issues caused by using this option. You are on your own!");
LOGGER.error("------------------------------------------------------------------------------------------------------------");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public static void setEnvironmentVariable(String name, @Nullable String value) {
MemoryUtil.memUTF16(value, true, lpValueBuf);
}

JNI.callJJI(MemoryUtil.memAddress0(lpNameBuf), MemoryUtil.memAddressSafe(lpValueBuf), PFN_SetEnvironmentVariableW);
JNI.callPPI(MemoryUtil.memAddress0(lpNameBuf), MemoryUtil.memAddressSafe(lpValueBuf), PFN_SetEnvironmentVariableW);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package me.jellysquid.mods.sodium.client.util.workarounds.platform.windows;

import net.minecraft.util.Util;
import net.minecraft.util.WinNativeModuleUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

public class WindowsModuleChecks {
private static final Logger LOGGER = LoggerFactory.getLogger("Sodium-Win32ModuleChecks");

public static void checkModules() {
if (Util.getOperatingSystem() != Util.OperatingSystem.WINDOWS) {
return;
}

LOGGER.warn("Checking for problematic loaded Win32 modules... (this may take a moment)");

List<WinNativeModuleUtil.NativeModule> modules;

try {
modules = WinNativeModuleUtil.collectNativeModules();
} catch (Throwable t) {
LOGGER.warn("Failed to scan the currently loaded modules", t);
return;
}

// RivaTuner hooks the wglCreateContext function, and leaves itself behind as a loaded module
if (Boolean.parseBoolean(System.getProperty("sodium.checks.win32.rtss", "true")) && modules.stream().anyMatch(module -> module.path.equalsIgnoreCase("RTSSHooks64.dll"))) {
LOGGER.error("------------------------------------------------------------------------------------------------------------");
LOGGER.error("READ ME! You appear to be using the RivaTuner Statistics Server (RTSS)!");
LOGGER.error(" * Rivatuner will cause extreme performance issues when using Sodium, and it will likely fill up your hard drive");
LOGGER.error(" with error logs.");
LOGGER.error(" * You must fully disable (or uninstall) the RivaTuner Statistics Server.");
LOGGER.error(" * If you don't remember installing RivaTuner, check to see if you have MSI Afterburner installed.");
LOGGER.error(" * For more information on possible workarounds and alternatives to Rivatuner, see the following issue on GitHub:");
LOGGER.error(" https://github.com/CaffeineMC/sodium-fabric/issues/2048");
LOGGER.error(" * HINT: If you believe this is an error, then you can force the game to start anyways by adding the " +
"following JVM argument.");
LOGGER.error(" -Dsodium.checks.win32.rtss" + "=false");
LOGGER.error(" * NOTE: We will not provide support for any issues caused by using this option. You are on your own!");
LOGGER.error("------------------------------------------------------------------------------------------------------------");

throw new RuntimeException("RivaTuner Statistics Server (RTSS) is not compatible with Sodium, " +
"see this issue for more details: https://github.com/CaffeineMC/sodium-fabric/issues/2048");
}
}
}
Loading

0 comments on commit 88b6c09

Please sign in to comment.