Skip to content

Commit

Permalink
Frametime exploration (#742)
Browse files Browse the repository at this point in the history
* Sleep before swap

* Add a config

* I think this is slightly less jittery
  • Loading branch information
ah-OOG-ah authored Dec 6, 2024
1 parent 70d15f2 commit f738adb
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -153,4 +153,8 @@ public class AngelicaConfig {
@Config.RangeDouble(min = 16D, max = 64D)
public static double mobSpawnerRenderDistance;

@Config.Comment("Switches to an alternate FPS limiter that gives more stable frametimes, in exchange for slightly " +
"more latency. Will never introduce more than one frame of latency, and has a lower impact at higher framerates.")
@Config.DefaultBoolean(false)
public static boolean sleepBeforeSwap;
}
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,15 @@ else if(Minecraft.getMinecraft().currentScreen instanceof SodiumOptionsGUI oldGu
}
}, (opts) -> opts.fullScreen)
.build())
.add(OptionImpl.createBuilder(boolean.class, angelicaOpts)
.setName(I18n.format("options.angelica.sleepbeforeswap"))
.setTooltip(I18n.format("options.angelica.sleepbeforeswap.tooltip"))
.setControl(TickBoxControl::new)
.setBinding((opts, value) -> {
AngelicaConfig.sleepBeforeSwap = value;
}, opts -> AngelicaConfig.sleepBeforeSwap)
.setImpact(OptionImpact.VARIES)
.build())
.add(OptionImpl.createBuilder(boolean.class, vanillaOpts)
.setName(I18n.format("options.vsync"))
.setTooltip(I18n.format("sodium.options.v_sync.tooltip"))
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/assets/angelica/lang/en_US.lang
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ options.angelica.mobSpawnerRenderDistance=Mod spawner render distance
options.angelica.mobSpawnerRenderDistance.tooltip=Render distance for the spinning mob inside mod spawners
options.angelica.itemdisplaylistcount=Item Renderer Display List Cache Size
options.angelica.itemdisplaylistcount.tooltip=The maximum number of display lists to cache in the optimized item renderer. Higher values will increase performance but increase VRAM usage.
options.angelica.sleepbeforeswap=Alternate FPS Limiter
options.angelica.sleepbeforeswap.tooltip=Switches to an alternate FPS limiter that gives more stable frametimes, in exchange for slightly more latency. Will never introduce more than one frame of latency, and has a lower impact at higher framerates.
pack.iris.select.title=Select
pack.iris.configure.title=Configure
label.iris.true=On
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.gtnewhorizons.angelica.mixins.early.angelica;

import com.gtnewhorizons.angelica.AngelicaMod;
import com.gtnewhorizons.angelica.config.AngelicaConfig;
import com.gtnewhorizons.angelica.mixins.interfaces.IGameSettingsExt;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.client.Minecraft;
import net.minecraft.client.settings.GameSettings;
import org.lwjgl.input.Keyboard;
Expand All @@ -14,10 +17,16 @@
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

@Mixin(Minecraft.class)
public class MixinMinecraft {
public abstract class MixinMinecraft {
@Shadow
public GameSettings gameSettings;

@Shadow
public abstract boolean isFramerateLimitBelowMax();

@Shadow
public abstract int getLimitFramerate();

@Unique
private long angelica$lastFrameTime = 0;

Expand All @@ -29,6 +38,20 @@ public class MixinMinecraft {
GL11.glEnable(GL11.GL_LIGHTING);
}

@Inject(
method = "func_147120_f",
at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/Display;update()V", shift = At.Shift.BEFORE, remap = false)
)
private void angelica$limitFPS(CallbackInfo ci) {
if (!AngelicaConfig.sleepBeforeSwap) return;
if (isFramerateLimitBelowMax()) {
final long target = angelica$lastFrameTime + (long) (1.0 / getLimitFramerate() * 1_000_000) * 1_000;
while (target - System.nanoTime() > 100) {
Thread.yield();
}
}
}

@Inject(
method = "func_147120_f",
at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/Display;update()V", shift = At.Shift.AFTER, remap = false)
Expand All @@ -41,6 +64,12 @@ public class MixinMinecraft {
angelica$lastFrameTime = time;
}

@WrapOperation(method = "runGameLoop", at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/Display;sync(I)V"))
private void angelica$noopFPSLimiter(int fps, Operation<Void> original) {
if (AngelicaConfig.sleepBeforeSwap) return;
original.call(fps);
}

@Inject(method = "runTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiScreen;isShiftKeyDown()Z", shift = At.Shift.AFTER))
private void angelica$setShowFpsGraph(CallbackInfo ci) {
((IGameSettingsExt) gameSettings).angelica$setShowFpsGraph(Keyboard.isKeyDown(Keyboard.KEY_LMENU) || Keyboard.isKeyDown(Keyboard.KEY_RMENU));
Expand Down

0 comments on commit f738adb

Please sign in to comment.