Completely bypass Minecraft when window is resized during rendering

Should fix issues where resizing affects the render result.
This commit is contained in:
Jonas Herzig
2022-04-10 18:36:36 +02:00
parent fd9be55f79
commit 5be57681af
10 changed files with 102 additions and 43 deletions

View File

@@ -1,5 +1,6 @@
package com.replaymod.render.gui.progress; package com.replaymod.render.gui.progress;
import com.replaymod.render.hooks.MinecraftClientExt;
import com.replaymod.render.mixin.MainWindowAccessor; import com.replaymod.render.mixin.MainWindowAccessor;
import de.johni0702.minecraft.gui.function.Closeable; import de.johni0702.minecraft.gui.function.Closeable;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
@@ -16,6 +17,7 @@ public class VirtualWindow implements Closeable {
private final MainWindowAccessor acc; private final MainWindowAccessor acc;
private final Framebuffer guiFramebuffer; private final Framebuffer guiFramebuffer;
private boolean isBound;
private int framebufferWidth, framebufferHeight; private int framebufferWidth, framebufferHeight;
private int gameWidth, gameHeight; private int gameWidth, gameHeight;
@@ -26,7 +28,8 @@ public class VirtualWindow implements Closeable {
this.window = mc.getWindow(); this.window = mc.getWindow();
this.acc = (MainWindowAccessor) (Object) this.window; this.acc = (MainWindowAccessor) (Object) this.window;
updateFramebufferSize(); framebufferWidth = acc.getFramebufferWidth();
framebufferHeight = acc.getFramebufferHeight();
//#if MC>=11700 //#if MC>=11700
//$$ guiFramebuffer = new WindowFramebuffer(framebufferWidth, framebufferHeight); //$$ guiFramebuffer = new WindowFramebuffer(framebufferWidth, framebufferHeight);
@@ -37,11 +40,15 @@ public class VirtualWindow implements Closeable {
//#endif //#endif
); );
//#endif //#endif
MinecraftClientExt.get(mc).setWindowDelegate(this);
} }
@Override @Override
public void close() { public void close() {
guiFramebuffer.delete(); guiFramebuffer.delete();
MinecraftClientExt.get(mc).setWindowDelegate(null);
} }
public void bind() { public void bind() {
@@ -49,11 +56,13 @@ public class VirtualWindow implements Closeable {
gameHeight = acc.getFramebufferHeight(); gameHeight = acc.getFramebufferHeight();
acc.setFramebufferWidth(framebufferWidth); acc.setFramebufferWidth(framebufferWidth);
acc.setFramebufferHeight(framebufferHeight); acc.setFramebufferHeight(framebufferHeight);
isBound = true;
} }
public void unbind() { public void unbind() {
acc.setFramebufferWidth(gameWidth); acc.setFramebufferWidth(gameWidth);
acc.setFramebufferHeight(gameHeight); acc.setFramebufferHeight(gameHeight);
isBound = false;
} }
public void beginWrite() { public void beginWrite() {
@@ -82,36 +91,45 @@ public class VirtualWindow implements Closeable {
//#endif //#endif
} }
public void updateSize() { /**
// Resize the GUI framebuffer if the display size changed * Updates the size of the window's framebuffer. Must only be called while this window is bound.
if (framebufferSizeChanged()) { */
updateFramebufferSize(); public void onResolutionChanged(int newWidth, int newHeight) {
//#if MC>=11400 if (newWidth == 0 || newHeight == 0) {
guiFramebuffer.resize(framebufferWidth, framebufferHeight
//#if MC>=11400
, false
//#endif
);
//#else
//$$ guiFramebuffer.createBindFramebuffer(framebufferWidth, framebufferHeight);
//#endif
}
}
private boolean framebufferSizeChanged() {
int realWidth = mc.getWindow().getFramebufferWidth();
int realHeight = mc.getWindow().getFramebufferHeight();
if (realWidth == 0 || realHeight == 0) {
// These can be zero on Windows if minimized. // These can be zero on Windows if minimized.
// Creating zero-sized framebuffers however will throw an error, so we never want to switch to zero values. // Creating zero-sized framebuffers however will throw an error, so we never want to switch to zero values.
return false; return;
}
if (framebufferWidth == newWidth && framebufferHeight == newHeight) {
return; // size is unchanged, nothing to do
}
framebufferWidth = newWidth;
framebufferHeight = newHeight;
//#if MC>=11400
guiFramebuffer.resize(newWidth, newHeight
//#if MC>=11400
, false
//#endif
);
//#else
//$$ guiFramebuffer.createBindFramebuffer(newWidth, newHeight);
//#endif
applyScaleFactor();
if (mc.currentScreen != null) {
mc.currentScreen.resize(mc, window.getScaledWidth(), window.getScaledHeight());
} }
return framebufferWidth != realWidth || framebufferHeight != realHeight;
} }
private void updateFramebufferSize() { private void applyScaleFactor() {
framebufferWidth = mc.getWindow().getFramebufferWidth(); //#if MC>=11400
framebufferHeight = mc.getWindow().getFramebufferHeight(); window.setScaleFactor(window.calculateScaleFactor(mc.options.guiScale, mc.forcesUnicodeFont()));
//#else
//$$ // Nothing to do, ScaledResolution re-computes the scale factor every time it is created
//#endif
} }
public int getFramebufferWidth() { public int getFramebufferWidth() {
@@ -121,4 +139,8 @@ public class VirtualWindow implements Closeable {
public int getFramebufferHeight() { public int getFramebufferHeight() {
return framebufferHeight; return framebufferHeight;
} }
public boolean isBound() {
return isBound;
}
} }

View File

@@ -0,0 +1,12 @@
package com.replaymod.render.hooks;
import com.replaymod.render.gui.progress.VirtualWindow;
import net.minecraft.client.MinecraftClient;
public interface MinecraftClientExt {
void setWindowDelegate(VirtualWindow window);
static MinecraftClientExt get(MinecraftClient mc) {
return (MinecraftClientExt) mc;
}
}

View File

@@ -15,12 +15,4 @@ public interface MainWindowAccessor {
int getFramebufferHeight(); int getFramebufferHeight();
@Accessor @Accessor
void setFramebufferHeight(int value); void setFramebufferHeight(int value);
// FIXME preprocessor should be able to infer this mapping
// FIXME preprocessor should be able to remap this one when the mapping is given manually
//#if MC>=11500
@Invoker
//#else
//$$ @Invoker("method_4483")
//#endif
void invokeUpdateFramebufferSize();
} }

View File

@@ -0,0 +1,39 @@
package com.replaymod.render.mixin;
import com.replaymod.render.gui.progress.VirtualWindow;
import com.replaymod.render.hooks.MinecraftClientExt;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.util.Window;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(MinecraftClient.class)
public class Mixin_SuppressFramebufferResizeDuringRender implements MinecraftClientExt {
@Unique
private VirtualWindow windowDelegate;
@Override
public void setWindowDelegate(VirtualWindow window) {
this.windowDelegate = window;
}
//#if MC>=11400
@Inject(method = "onResolutionChanged", at = @At("HEAD"), cancellable = true)
//#else
//$$ @Inject(method = "resize", at = @At("HEAD"), cancellable = true)
//#endif
private void suppressResizeDuringRender(CallbackInfo ci) {
VirtualWindow delegate = this.windowDelegate;
if (delegate != null && delegate.isBound()) {
Window window = ((MinecraftClient) (Object) this).getWindow();
delegate.onResolutionChanged(window.getFramebufferWidth(), window.getFramebufferHeight());
ci.cancel();
}
}
}

View File

@@ -462,8 +462,6 @@ public class VideoRenderer implements RenderInfo {
return false; return false;
} }
guiWindow.updateSize();
pushMatrix(); pushMatrix();
GlStateManager.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT GlStateManager.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT
//#if MC>=11400 //#if MC>=11400

View File

@@ -21,6 +21,7 @@
"Mixin_StabilizeCamera", "Mixin_StabilizeCamera",
"Mixin_Stereoscopic_Camera", "Mixin_Stereoscopic_Camera",
"Mixin_Stereoscopic_HandRenderPass", "Mixin_Stereoscopic_HandRenderPass",
"Mixin_SuppressFramebufferResizeDuringRender",
//#if MC>=11600 //#if MC>=11600
"Mixin_AddIrisOdsShaderUniforms", "Mixin_AddIrisOdsShaderUniforms",
"Mixin_LoadIrisOdsShaderPack", "Mixin_LoadIrisOdsShaderPack",

View File

@@ -33,11 +33,6 @@ public class Window implements MainWindowAccessor {
mc.displayHeight = value; mc.displayHeight = value;
} }
@Override
public void invokeUpdateFramebufferSize() {
// no-op, pre-LWJGL3 MC doesn't differentiate between window and framebuffer size
}
public long getHandle() { public long getHandle() {
return 0; return 0;
} }

View File

@@ -15,6 +15,4 @@ public interface MainWindowAccessor {
int getFramebufferHeight(); int getFramebufferHeight();
@Accessor("displayHeight") @Accessor("displayHeight")
void setFramebufferHeight(int value); void setFramebufferHeight(int value);
@Invoker
void invokeUpdateFramebufferSize();
} }

View File

@@ -181,6 +181,7 @@ net.minecraft.client.gui.screen.Screen hasShiftDown() isShiftKeyDown()
net.minecraft.client.gui.screen.Screen init() setWorldAndResolution() net.minecraft.client.gui.screen.Screen init() setWorldAndResolution()
net.minecraft.client.gui.screen.Screen minecraft mc net.minecraft.client.gui.screen.Screen minecraft mc
net.minecraft.client.gui.screen.Screen net.minecraft.client.gui.GuiScreen net.minecraft.client.gui.screen.Screen net.minecraft.client.gui.GuiScreen
net.minecraft.client.gui.screen.Screen resize() onResize()
net.minecraft.client.gui.screen.Screen passEvents allowUserInput net.minecraft.client.gui.screen.Screen passEvents allowUserInput
net.minecraft.client.gui.screen.Screen removed() onGuiClosed() net.minecraft.client.gui.screen.Screen removed() onGuiClosed()
net.minecraft.client.gui.screen.Screen renderBackground() drawDefaultBackground() net.minecraft.client.gui.screen.Screen renderBackground() drawDefaultBackground()

View File

@@ -1,3 +1,4 @@
net.minecraft.client.gui.GuiScreen onResize() func_175273_b()
net.minecraft.entity.player.EntityPlayer isWearing() func_175148_a() net.minecraft.entity.player.EntityPlayer isWearing() func_175148_a()
net.minecraft.client.renderer.WorldRenderer begin() startDrawing() net.minecraft.client.renderer.WorldRenderer begin() startDrawing()
net.minecraft.network.play.server.S38PacketPlayerListItem getAction() func_179768_b() net.minecraft.network.play.server.S38PacketPlayerListItem getAction() func_179768_b()