mirror of
https://github.com/GTNewHorizons/Angelica.git
synced 2026-11-08 12:35:01 +00:00
Stop resetting SDL GPU to OpenGL on unrelated crashes (#2266)
This commit is contained in:
1 parent
f81ee4b03a
commit
8e1809622c
9 files changed
+125
-77
No files matched your search
@@ -245,7 +245,6 @@ public class GLContextState {
|
||||
public final int[] clientAttribSavedPackBuffer = new int[GLStateManager.CLIENT_ATTRIB_STACK_DEPTH];
|
||||
public final VAOManager.ClientArrays[] clientAttribSavedArrays = new VAOManager.ClientArrays[GLStateManager.CLIENT_ATTRIB_STACK_DEPTH];
|
||||
public int clientAttribStackPointer = 0;
|
||||
public float maxPointSize = Float.NaN;
|
||||
public int restoreChangedMask;
|
||||
public long restoreUnitChangedMask;
|
||||
public final BlendState vanillaBlendBefore = new BlendState();
|
||||
|
||||
@@ -415,6 +415,7 @@ public class GLStateManager {
|
||||
|
||||
// This setting varies depending on driver, so it gets queried at runtime
|
||||
public static int DEFAULT_DRAW_BUFFER = GL11.GL_BACK;
|
||||
private static float maxPointSize;
|
||||
|
||||
private static volatile Thread CurrentThread = MainThread;
|
||||
@Setter @Getter private static boolean runningSplash = true;
|
||||
@@ -517,18 +518,6 @@ public class GLStateManager {
|
||||
}
|
||||
}
|
||||
|
||||
private static float maxPointSize(GLContextState glCtx) {
|
||||
if (Float.isNaN(glCtx.maxPointSize)) {
|
||||
final FloatBuffer range = glCtx.queryScratch;
|
||||
range.clear();
|
||||
RENDER_BACKEND.getFloat(GL11.GL_POINT_SIZE_RANGE, range);
|
||||
final float smooth = range.get(1);
|
||||
RENDER_BACKEND.getFloat(GL12.GL_ALIASED_POINT_SIZE_RANGE, range);
|
||||
glCtx.maxPointSize = Math.max(smooth, range.get(1));
|
||||
}
|
||||
return glCtx.maxPointSize;
|
||||
}
|
||||
|
||||
private static <T extends CowStateStack<?>> T mod(T s) {
|
||||
s.beforeModify();
|
||||
return s;
|
||||
@@ -777,6 +766,13 @@ public class GLStateManager {
|
||||
initCallback.run();
|
||||
}
|
||||
|
||||
final FloatBuffer range = glCtx.queryScratch;
|
||||
range.clear();
|
||||
RENDER_BACKEND.getFloat(GL11.GL_POINT_SIZE_RANGE, range);
|
||||
final float smooth = range.get(1);
|
||||
RENDER_BACKEND.getFloat(GL12.GL_ALIASED_POINT_SIZE_RANGE, range);
|
||||
maxPointSize = Math.max(smooth, range.get(1));
|
||||
|
||||
// Drain any pending GL errors from initialization. In core profile, some legacy queries may generate GL_INVALID_ENUM. The splash thread inherits the
|
||||
// DrawableGL context and its error state, so stale errors here would cause SplashProgress.checkGLError() to fail.
|
||||
int err;
|
||||
@@ -1482,7 +1478,7 @@ public class GLStateManager {
|
||||
case GL11.GL_LINE_WIDTH -> glCtx.lineState.getWidth();
|
||||
case GL11.GL_POINT_SIZE -> glCtx.pointState.getSize();
|
||||
case GL14.GL_POINT_SIZE_MIN -> glCtx.pointState.getMinSize();
|
||||
case GL14.GL_POINT_SIZE_MAX -> Float.isNaN(glCtx.pointState.getMaxSize()) ? maxPointSize(glCtx) : glCtx.pointState.getMaxSize();
|
||||
case GL14.GL_POINT_SIZE_MAX -> Float.isNaN(glCtx.pointState.getMaxSize()) ? maxPointSize : glCtx.pointState.getMaxSize();
|
||||
case GL14.GL_POINT_FADE_THRESHOLD_SIZE -> glCtx.pointState.getFadeThreshold();
|
||||
default -> {
|
||||
final int desc = isCachingEnabled() ? LegacyQueries.desc(pname) : 0;
|
||||
|
||||
@@ -21,7 +21,11 @@ public final class BackendOptions {
|
||||
}
|
||||
|
||||
public static String sdlGpuDriver() {
|
||||
return SystemProperties.SDL_GPU_DRIVER_OVERRIDE != null ? SystemProperties.SDL_GPU_DRIVER_OVERRIDE : configDriver;
|
||||
return sdlGpuDriver(configDriver);
|
||||
}
|
||||
|
||||
public static String sdlGpuDriver(String driver) {
|
||||
return SystemProperties.SDL_GPU_DRIVER_OVERRIDE != null ? SystemProperties.SDL_GPU_DRIVER_OVERRIDE : driver;
|
||||
}
|
||||
|
||||
public static boolean configSdlGpu() {
|
||||
|
||||
@@ -1,55 +1,96 @@
|
||||
package com.gtnewhorizons.angelica.glsm.backend;
|
||||
|
||||
import com.google.common.primitives.Ints;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
|
||||
public final class BackendStartGuard {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger("Angelica/BackendStartGuard");
|
||||
|
||||
private static File pending;
|
||||
static final int STRIKE_LIMIT = 3;
|
||||
|
||||
private static File marker;
|
||||
private static File verified;
|
||||
private static String key;
|
||||
private static int strikes;
|
||||
private static boolean pending;
|
||||
private static boolean tripped;
|
||||
|
||||
private BackendStartGuard() {}
|
||||
|
||||
public static boolean begin(File marker, boolean sdlGpuConfigured, boolean flagForced) {
|
||||
pending = null;
|
||||
tripped = false;
|
||||
if (!sdlGpuConfigured || flagForced) {
|
||||
public static boolean begin(File dir, boolean sdlGpuConfigured, boolean flagForced, int requirementsRevision, String requestedDriver) {
|
||||
marker = new File(dir, "sdlgpu-starting");
|
||||
verified = new File(dir, "sdlgpu-verified");
|
||||
key = requirementsRevision + "/" + requestedDriver;
|
||||
pending = tripped = false;
|
||||
if (flagForced) return false;
|
||||
if (!sdlGpuConfigured) {
|
||||
delete(marker);
|
||||
return false;
|
||||
}
|
||||
if (marker.isFile()) {
|
||||
if (key.equals(read(verified))) return false;
|
||||
final String count = read(marker);
|
||||
final Integer parsed = count == null ? null : Ints.tryParse(count.trim());
|
||||
strikes = parsed == null ? 0 : parsed;
|
||||
if (strikes >= STRIKE_LIMIT) {
|
||||
LOGGER.warn("SDL GPU failed to bring up the device {} times in a row; resetting the render backend to OpenGL", strikes);
|
||||
delete(marker);
|
||||
tripped = true;
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
final File dir = marker.getParentFile();
|
||||
if (dir != null && !dir.isDirectory() && !dir.mkdirs()) throw new IOException("cannot create " + dir);
|
||||
if (marker.createNewFile()) pending = marker;
|
||||
} catch (IOException e) {
|
||||
LOGGER.warn("Could not write {}: {}", marker, e.toString());
|
||||
if (strikes == STRIKE_LIMIT - 1) {
|
||||
LOGGER.warn("SDL GPU failed to bring up the device {} times in a row; one more and the render backend switches to OpenGL", strikes);
|
||||
} else if (strikes > 0) {
|
||||
LOGGER.info("The last start ended while bringing up the SDL GPU device");
|
||||
}
|
||||
pending = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void finish() {
|
||||
if (pending == null) return;
|
||||
delete(pending);
|
||||
pending = null;
|
||||
public static void arm() {
|
||||
if (pending) write(marker, Integer.toString(strikes + 1));
|
||||
}
|
||||
|
||||
public static void disarm() {
|
||||
if (pending) delete(marker);
|
||||
}
|
||||
|
||||
public static void latch() {
|
||||
if (!pending) return;
|
||||
pending = false;
|
||||
write(verified, key);
|
||||
LOGGER.info("SDL GPU booted; the startup guard stays off until the requirements revision or driver changes");
|
||||
}
|
||||
|
||||
public static boolean tripped() {
|
||||
return tripped;
|
||||
}
|
||||
|
||||
private static void delete(File marker) {
|
||||
if (marker.isFile() && !marker.delete()) {
|
||||
LOGGER.warn("Could not delete {}", marker);
|
||||
private static String read(File file) {
|
||||
try {
|
||||
return file.isFile() ? new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8) : null;
|
||||
} catch (IOException e) {
|
||||
LOGGER.warn("Could not read {}: {}", file, e.toString());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void write(File file, String content) {
|
||||
try {
|
||||
Files.createDirectories(file.toPath().getParent());
|
||||
Files.write(file.toPath(), content.getBytes(StandardCharsets.UTF_8));
|
||||
} catch (IOException e) {
|
||||
LOGGER.warn("Could not write {}: {}", file, e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private static void delete(File file) {
|
||||
if (file.isFile() && !file.delete()) LOGGER.warn("Could not delete {}", file);
|
||||
}
|
||||
}
|
||||
+38
-39
@@ -4,7 +4,6 @@ import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
@@ -12,54 +11,54 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class BackendStartGuardTest {
|
||||
|
||||
private static File marker(Path dir) {
|
||||
return dir.resolve("angelica").resolve("sdlgpu-starting").toFile();
|
||||
@TempDir
|
||||
Path dir;
|
||||
|
||||
private boolean boot() {
|
||||
return boot(1);
|
||||
}
|
||||
|
||||
private boolean boot(int revision) {
|
||||
return BackendStartGuard.begin(dir.toFile(), true, false, revision, "");
|
||||
}
|
||||
|
||||
private File marker() {
|
||||
return dir.resolve("sdlgpu-starting").toFile();
|
||||
}
|
||||
|
||||
@Test
|
||||
void firstStartCreatesTheMarkerAndFinishRemovesIt(@TempDir Path dir) {
|
||||
final File marker = marker(dir);
|
||||
assertFalse(BackendStartGuard.begin(marker, true, false));
|
||||
assertFalse(BackendStartGuard.tripped());
|
||||
assertTrue(marker.isFile());
|
||||
BackendStartGuard.finish();
|
||||
assertFalse(marker.exists());
|
||||
void bootsThatReachTheBackendNeverCountAsStrikes() {
|
||||
for (int i = 0; i < BackendStartGuard.STRIKE_LIMIT; i++) {
|
||||
assertFalse(boot());
|
||||
BackendStartGuard.arm();
|
||||
BackendStartGuard.disarm();
|
||||
}
|
||||
assertFalse(boot());
|
||||
}
|
||||
|
||||
@Test
|
||||
void leftoverMarkerTripsOnceAndIsRemoved(@TempDir Path dir) {
|
||||
final File marker = marker(dir);
|
||||
assertFalse(BackendStartGuard.begin(marker, true, false));
|
||||
assertTrue(BackendStartGuard.begin(marker, true, false));
|
||||
void thirdDeathInTheDeviceWindowResets() {
|
||||
for (int i = 0; i < BackendStartGuard.STRIKE_LIMIT; i++) {
|
||||
assertFalse(boot());
|
||||
BackendStartGuard.arm();
|
||||
}
|
||||
assertTrue(boot());
|
||||
assertTrue(BackendStartGuard.tripped());
|
||||
assertFalse(marker.exists());
|
||||
BackendStartGuard.finish();
|
||||
assertFalse(marker.exists());
|
||||
assertFalse(BackendStartGuard.begin(marker, true, false));
|
||||
assertFalse(BackendStartGuard.tripped());
|
||||
BackendStartGuard.finish();
|
||||
assertFalse(marker().exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
void openGlConfigWritesNoMarkerAndClearsAStaleOne(@TempDir Path dir) throws IOException {
|
||||
final File marker = marker(dir);
|
||||
assertFalse(BackendStartGuard.begin(marker, false, false));
|
||||
assertFalse(marker.exists());
|
||||
assertTrue(marker.getParentFile().mkdirs());
|
||||
assertTrue(marker.createNewFile());
|
||||
assertFalse(BackendStartGuard.begin(marker, false, false));
|
||||
assertFalse(BackendStartGuard.tripped());
|
||||
assertFalse(marker.exists());
|
||||
}
|
||||
void latchStopsArmingUntilTheRequirementsRevisionChanges() {
|
||||
assertFalse(boot());
|
||||
BackendStartGuard.arm();
|
||||
BackendStartGuard.disarm();
|
||||
BackendStartGuard.latch();
|
||||
assertFalse(boot());
|
||||
BackendStartGuard.arm();
|
||||
assertFalse(marker().exists());
|
||||
|
||||
@Test
|
||||
void forcedFlagNeverTripsOrWrites(@TempDir Path dir) throws IOException {
|
||||
final File marker = marker(dir);
|
||||
assertFalse(BackendStartGuard.begin(marker, true, true));
|
||||
assertFalse(marker.exists());
|
||||
assertTrue(marker.getParentFile().mkdirs());
|
||||
assertTrue(marker.createNewFile());
|
||||
assertFalse(BackendStartGuard.begin(marker, true, true));
|
||||
assertFalse(BackendStartGuard.tripped());
|
||||
assertFalse(boot(2));
|
||||
BackendStartGuard.arm();
|
||||
assertTrue(marker().isFile());
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import static org.lwjgl.sdl.SDLVideo.SDL_PROP_WINDOW_CREATE_METAL_BOOLEAN;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.backend.BackendOptions;
|
||||
import com.gtnewhorizons.angelica.glsm.backend.BackendManager;
|
||||
import com.gtnewhorizons.angelica.glsm.backend.BackendStartGuard;
|
||||
import com.gtnewhorizons.angelica.glsm.backend.RenderBackend;
|
||||
import com.gtnewhorizons.angelica.glsm.loading.DependencyVerifier;
|
||||
import com.gtnewhorizons.angelica.glsm.loading.DependencyVerifier.Check;
|
||||
@@ -55,6 +56,7 @@ public final class SDLGPUGate {
|
||||
}
|
||||
|
||||
public static final String LWJGL3IFY_MIN_VERSION = "3.0.25";
|
||||
public static final int REQUIREMENTS_REVISION = 1;
|
||||
|
||||
private static final List<Check> REQUIREMENTS = List.of(
|
||||
new Check("/org/lwjgl/sdl/SDLGPU.class", "no lwjgl-sdl on the classpath"),
|
||||
@@ -90,12 +92,16 @@ public final class SDLGPUGate {
|
||||
boolean ok;
|
||||
try {
|
||||
Sys.initialize();
|
||||
BackendStartGuard.arm();
|
||||
ok = MainThreadExec.runOnMainThread(device()::createDevice);
|
||||
} catch (Throwable t) {
|
||||
LOG.error("SDL GPU device probe failed", t);
|
||||
ok = false;
|
||||
}
|
||||
if (!ok) resetSdlLogging();
|
||||
if (!ok) {
|
||||
resetSdlLogging();
|
||||
BackendStartGuard.disarm();
|
||||
}
|
||||
deviceReady = ok;
|
||||
return ok;
|
||||
}
|
||||
@@ -182,6 +188,7 @@ public final class SDLGPUGate {
|
||||
throw new IllegalStateException("Celeritas already selected the SDL GPU LWJGL service; falling back to OpenGL would leave it bound to a dead backend");
|
||||
}
|
||||
SDLGPULWJGLService.unbind();
|
||||
BackendStartGuard.disarm();
|
||||
disarmed = true;
|
||||
engaged = false;
|
||||
deviceReady = false;
|
||||
|
||||
@@ -72,8 +72,7 @@ public final class AngelicaClientTweaker implements IFMLLoadingPlugin, IEarlyMix
|
||||
// Angelica Config
|
||||
ConfigurationManager.registerConfig(AngelicaConfig.class);
|
||||
TracyOptions.latch(AngelicaConfig.enableTracy, AngelicaConfig.tracyAllowRemote, AngelicaConfig.tracyFineZones, AngelicaConfig.tracyMaxSrcLocs);
|
||||
if (BackendStartGuard.begin(new File(Launch.minecraftHome, "angelica" + File.separator + "sdlgpu-starting"), AngelicaConfig.sdlGpuConfigured(), SystemProperties.SDL_GPU_OVERRIDE != null)) {
|
||||
LOGGER.warn("The last start with SDL GPU did not reach the main menu; resetting the render backend to OpenGL");
|
||||
if (BackendStartGuard.begin(new File(Launch.minecraftHome, "angelica"), AngelicaConfig.sdlGpuConfigured(), SystemProperties.SDL_GPU_OVERRIDE != null, SDLGPUGate.REQUIREMENTS_REVISION, BackendOptions.sdlGpuDriver(AngelicaConfig.sdlGpuDriverName()))) {
|
||||
AngelicaConfig.renderBackend = RenderBackendChoice.OPENGL;
|
||||
ConfigurationManager.save(AngelicaConfig.class);
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@ import com.gtnewhorizons.angelica.debug.TPSGraph;
|
||||
import com.gtnewhorizons.angelica.dynamiclights.DynamicLights;
|
||||
import com.gtnewhorizons.angelica.dynamiclights.config.EntityLightConfig;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.backend.BackendManager;
|
||||
import com.gtnewhorizons.angelica.glsm.backend.BackendStartGuard;
|
||||
import com.gtnewhorizons.angelica.glsm.backend.VSyncMode;
|
||||
import com.gtnewhorizons.angelica.glsm.profiling.Tracy;
|
||||
@@ -383,7 +384,7 @@ public final class ClientProxy extends CommonProxy {
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.LOWEST)
|
||||
public void onGuiOpen(GuiOpenEvent event) {
|
||||
BackendStartGuard.finish();
|
||||
if (BackendManager.RENDER_BACKEND.isSDLGPU()) BackendStartGuard.latch();
|
||||
if (!event.isCanceled()) {
|
||||
if (event.gui instanceof GuiMainMenu && gameStartTime == -1) {
|
||||
gameStartTime = ManagementFactory.getRuntimeMXBean().getUptime() / 1000f;
|
||||
|
||||
+2
@@ -8,6 +8,7 @@ import com.gtnewhorizons.angelica.config.SystemProperties;
|
||||
import com.gtnewhorizons.angelica.compat.DriverCompatabilityCheck;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.backend.BackendManager;
|
||||
import com.gtnewhorizons.angelica.glsm.backend.BackendStartGuard;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.GLSMConfig;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.GLSMHooks;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.GLSMInitConfig;
|
||||
@@ -47,6 +48,7 @@ public class MixinInitGLStateManager {
|
||||
.enableDSA(AngelicaConfig.enableDSA)
|
||||
.postInitCallback(SelectionBoxRenderer::init)
|
||||
.build());
|
||||
BackendStartGuard.disarm();
|
||||
|
||||
GLSMConfig.extendedAttribsExpected = AngelicaConfig.enableIris;
|
||||
|
||||
|
||||
Reference in new issue
Block a user