From e68abfb45b85f9d14e6c387fe968077cd0d56a98 Mon Sep 17 00:00:00 2001 From: JellySquid Date: Thu, 20 Feb 2025 22:57:46 -0600 Subject: [PATCH] Use hardware copy for render target blits where possible Minecraft performs a blit using a fragment shader, which is unnecessary when blending is not used. Using the fixed function hardware to perform the blit is much faster and doesn't utilize the rasterization engine. This is a cherry-pick of cd18e7f9, 1ac46d0b, and e1bae361. --- .../client/data/config/MixinConfig.java | 2 + .../render/compositing/FramebufferMixin.java | 48 +++++++++++++++++++ src/main/resources/sodium.mixins.json | 1 + 3 files changed, 51 insertions(+) create mode 100644 src/main/java/me/jellysquid/mods/sodium/mixin/features/render/compositing/FramebufferMixin.java diff --git a/src/main/java/me/jellysquid/mods/sodium/client/data/config/MixinConfig.java b/src/main/java/me/jellysquid/mods/sodium/client/data/config/MixinConfig.java index f7d1254add..11b22e53d2 100644 --- a/src/main/java/me/jellysquid/mods/sodium/client/data/config/MixinConfig.java +++ b/src/main/java/me/jellysquid/mods/sodium/client/data/config/MixinConfig.java @@ -51,6 +51,8 @@ private MixinConfig() { this.addMixinRule("features.render", true); + this.addMixinRule("features.render.compositing", true); + this.addMixinRule("features.render.entity", true); this.addMixinRule("features.render.entity.cull", true); this.addMixinRule("features.render.entity.shadow", true); diff --git a/src/main/java/me/jellysquid/mods/sodium/mixin/features/render/compositing/FramebufferMixin.java b/src/main/java/me/jellysquid/mods/sodium/mixin/features/render/compositing/FramebufferMixin.java new file mode 100644 index 0000000000..3bbcdffd90 --- /dev/null +++ b/src/main/java/me/jellysquid/mods/sodium/mixin/features/render/compositing/FramebufferMixin.java @@ -0,0 +1,48 @@ +package me.jellysquid.mods.sodium.mixin.features.render.compositing; + + +import net.caffeinemc.mods.sodium.client.compatibility.workarounds.Workarounds; +import net.minecraft.client.gl.Framebuffer; +import org.lwjgl.opengl.GL32C; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(Framebuffer.class) +public class FramebufferMixin { + @Shadow + public int fbo; + + @Shadow + public int textureWidth; + + @Shadow + public int textureHeight; + + /** + * @author JellySquid + * @reason Use fixed function hardware for framebuffer blits + */ + @Inject(method = "drawInternal", at = @At("HEAD"), cancellable = true) + public void blitToScreen(int width, int height, boolean disableBlend, CallbackInfo ci) { + if (Workarounds.isWorkaroundEnabled(Workarounds.Reference.INTEL_FRAMEBUFFER_BLIT_CRASH_WHEN_UNFOCUSED)) { + return; + } + + if (disableBlend) { + ci.cancel(); + + // When blending is not used, we can directly copy the contents of one + // framebuffer to another using the blitting engine. This can save a lot of time + // when compared to going through the rasterization pipeline. + GL32C.glBindFramebuffer(GL32C.GL_READ_FRAMEBUFFER, this.fbo); + GL32C.glBlitFramebuffer( + 0, 0, width, height, + 0, 0, width, height, + GL32C.GL_COLOR_BUFFER_BIT, GL32C.GL_LINEAR); + GL32C.glBindFramebuffer(GL32C.GL_READ_FRAMEBUFFER, 0); + } + } +} diff --git a/src/main/resources/sodium.mixins.json b/src/main/resources/sodium.mixins.json index 3f9766ede2..367fb04af3 100644 --- a/src/main/resources/sodium.mixins.json +++ b/src/main/resources/sodium.mixins.json @@ -44,6 +44,7 @@ "features.options.render_layers.LeavesBlockMixin", "features.options.render_layers.RenderLayersMixin", "features.options.weather.WorldRendererMixin", + "features.render.compositing.FramebufferMixin", "features.render.entity.CuboidMixin", "features.render.entity.ModelPartMixin", "features.render.entity.cull.EntityRendererMixin",