From cc2a2a9e6addb3f00a433502068c6ed8d22c4c57 Mon Sep 17 00:00:00 2001 From: RaphiMC <50594595+RaphiMC@users.noreply.github.com> Date: Thu, 2 Jan 2025 19:58:19 +0100 Subject: [PATCH] Improved core shader modification detection --- .../compat/CoreShaderBlacklist.java | 30 ++++----- .../injection/interfaces/IShaderProgram.java | 32 +++++++++ .../mixins/core/compat/MixinShaderLoader.java | 38 ++++++++--- .../core/compat/MixinShaderProgram.java | 67 +++++++++++++++++++ .../immediatelyfast-common.mixins.json | 1 + .../resources/immediatelyfast.accesswidener | 3 +- 6 files changed, 142 insertions(+), 29 deletions(-) create mode 100644 common/src/main/java/net/raphimc/immediatelyfast/injection/interfaces/IShaderProgram.java create mode 100644 common/src/main/java/net/raphimc/immediatelyfast/injection/mixins/core/compat/MixinShaderProgram.java diff --git a/common/src/main/java/net/raphimc/immediatelyfast/compat/CoreShaderBlacklist.java b/common/src/main/java/net/raphimc/immediatelyfast/compat/CoreShaderBlacklist.java index f97c39d4..5fd28088 100644 --- a/common/src/main/java/net/raphimc/immediatelyfast/compat/CoreShaderBlacklist.java +++ b/common/src/main/java/net/raphimc/immediatelyfast/compat/CoreShaderBlacklist.java @@ -17,31 +17,27 @@ */ package net.raphimc.immediatelyfast.compat; +import net.minecraft.client.gl.ShaderProgramKey; import net.minecraft.client.gl.ShaderProgramKeys; -import net.minecraft.util.Identifier; import java.util.List; public class CoreShaderBlacklist { - private static final List BLACKLIST = List.of( - ShaderProgramKeys.POSITION_COLOR.configId(), - ShaderProgramKeys.POSITION_TEX.configId(), - ShaderProgramKeys.POSITION_TEX_COLOR.configId(), - ShaderProgramKeys.RENDERTYPE_TEXT.configId(), - ShaderProgramKeys.RENDERTYPE_TEXT_BACKGROUND.configId(), - ShaderProgramKeys.RENDERTYPE_TEXT_BACKGROUND_SEE_THROUGH.configId(), - ShaderProgramKeys.RENDERTYPE_TEXT_INTENSITY.configId(), - ShaderProgramKeys.RENDERTYPE_TEXT_INTENSITY_SEE_THROUGH.configId(), - ShaderProgramKeys.RENDERTYPE_TEXT_SEE_THROUGH.configId(), - ShaderProgramKeys.RENDERTYPE_ITEM_ENTITY_TRANSLUCENT_CULL.configId() + private static final List BLACKLIST = List.of( + ShaderProgramKeys.POSITION_COLOR, + ShaderProgramKeys.POSITION_TEX, + ShaderProgramKeys.POSITION_TEX_COLOR, + ShaderProgramKeys.RENDERTYPE_TEXT, + ShaderProgramKeys.RENDERTYPE_TEXT_BACKGROUND, + ShaderProgramKeys.RENDERTYPE_TEXT_BACKGROUND_SEE_THROUGH, + ShaderProgramKeys.RENDERTYPE_TEXT_INTENSITY, + ShaderProgramKeys.RENDERTYPE_TEXT_INTENSITY_SEE_THROUGH, + ShaderProgramKeys.RENDERTYPE_TEXT_SEE_THROUGH, + ShaderProgramKeys.RENDERTYPE_ITEM_ENTITY_TRANSLUCENT_CULL ); - public static boolean isBlacklisted(final Identifier identifier) { - return BLACKLIST.contains(identifier); - } - - public static List getBlacklist() { + public static List getBlacklist() { return BLACKLIST; } diff --git a/common/src/main/java/net/raphimc/immediatelyfast/injection/interfaces/IShaderProgram.java b/common/src/main/java/net/raphimc/immediatelyfast/injection/interfaces/IShaderProgram.java new file mode 100644 index 00000000..9cc6177d --- /dev/null +++ b/common/src/main/java/net/raphimc/immediatelyfast/injection/interfaces/IShaderProgram.java @@ -0,0 +1,32 @@ +/* + * This file is part of ImmediatelyFast - https://github.com/RaphiMC/ImmediatelyFast + * Copyright (C) 2023-2025 RK_01/RaphiMC and contributors + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.raphimc.immediatelyfast.injection.interfaces; + +import net.minecraft.client.gl.CompiledShader; + +public interface IShaderProgram { + + CompiledShader immediatelyFast$getVertexShader(); + + void immediatelyFast$setVertexShader(final CompiledShader vertexShader); + + CompiledShader immediatelyFast$getFragmentShader(); + + void immediatelyFast$setFragmentShader(final CompiledShader fragmentShader); + +} diff --git a/common/src/main/java/net/raphimc/immediatelyfast/injection/mixins/core/compat/MixinShaderLoader.java b/common/src/main/java/net/raphimc/immediatelyfast/injection/mixins/core/compat/MixinShaderLoader.java index 6abcb80b..35a3dc66 100644 --- a/common/src/main/java/net/raphimc/immediatelyfast/injection/mixins/core/compat/MixinShaderLoader.java +++ b/common/src/main/java/net/raphimc/immediatelyfast/injection/mixins/core/compat/MixinShaderLoader.java @@ -18,37 +18,55 @@ package net.raphimc.immediatelyfast.injection.mixins.core.compat; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gl.CompiledShader; import net.minecraft.client.gl.ShaderLoader; -import net.minecraft.client.gl.ShaderProgramDefinition; +import net.minecraft.client.gl.ShaderProgramKey; import net.minecraft.resource.Resource; import net.minecraft.resource.ResourceManager; import net.minecraft.util.Identifier; import net.minecraft.util.profiler.Profiler; import net.raphimc.immediatelyfast.ImmediatelyFast; import net.raphimc.immediatelyfast.compat.CoreShaderBlacklist; +import net.raphimc.immediatelyfast.injection.interfaces.IShaderProgram; 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; -import java.util.Map; - @Mixin(ShaderLoader.class) public abstract class MixinShaderLoader { + @Shadow + private ShaderLoader.Cache cache; + @Inject(method = "apply(Lnet/minecraft/client/gl/ShaderLoader$Definitions;Lnet/minecraft/resource/ResourceManager;Lnet/minecraft/util/profiler/Profiler;)V", at = @At("RETURN")) private void checkForCoreShaderModifications(ShaderLoader.Definitions definitions, ResourceManager resourceManager, Profiler profiler, CallbackInfo ci) { boolean modified = false; - for (Map.Entry entry : definitions.programs().entrySet()) { - if (!CoreShaderBlacklist.isBlacklisted(entry.getKey())) continue; - - final Resource resource = resourceManager.getResource(entry.getValue().vertex()).orElse(null); - if (resource != null && !resource.getPack().equals(MinecraftClient.getInstance().getDefaultResourcePack())) { - modified = true; - break; + try { + for (ShaderProgramKey shaderProgramKey : CoreShaderBlacklist.getBlacklist()) { + if (this.cache.getOrLoadProgram(shaderProgramKey) instanceof IShaderProgram mixinShaderProgram) { + if (mixinShaderProgram.immediatelyFast$getVertexShader() == null || mixinShaderProgram.immediatelyFast$getFragmentShader() == null) { + continue; + } + final Identifier vertexShaderIdentifier = CompiledShader.Type.VERTEX.createFinder().toResourcePath(mixinShaderProgram.immediatelyFast$getVertexShader().getId()); + final Resource vertexShaderResource = resourceManager.getResource(vertexShaderIdentifier).orElse(null); + if (vertexShaderResource != null && !vertexShaderResource.getPack().equals(MinecraftClient.getInstance().getDefaultResourcePack())) { + modified = true; + break; + } + final Identifier fragmentShaderIdentifier = CompiledShader.Type.FRAGMENT.createFinder().toResourcePath(mixinShaderProgram.immediatelyFast$getFragmentShader().getId()); + final Resource fragmentShaderResource = resourceManager.getResource(fragmentShaderIdentifier).orElse(null); + if (fragmentShaderResource != null && !fragmentShaderResource.getPack().equals(MinecraftClient.getInstance().getDefaultResourcePack())) { + modified = true; + break; + } + } } + } catch (ShaderLoader.LoadException e) { + ImmediatelyFast.LOGGER.error("Failed to check for core shader modifications", e); } if (modified && !ImmediatelyFast.config.experimental_disable_resource_pack_conflict_handling) { diff --git a/common/src/main/java/net/raphimc/immediatelyfast/injection/mixins/core/compat/MixinShaderProgram.java b/common/src/main/java/net/raphimc/immediatelyfast/injection/mixins/core/compat/MixinShaderProgram.java new file mode 100644 index 00000000..ebeb31c7 --- /dev/null +++ b/common/src/main/java/net/raphimc/immediatelyfast/injection/mixins/core/compat/MixinShaderProgram.java @@ -0,0 +1,67 @@ +/* + * This file is part of ImmediatelyFast - https://github.com/RaphiMC/ImmediatelyFast + * Copyright (C) 2023-2025 RK_01/RaphiMC and contributors + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.raphimc.immediatelyfast.injection.mixins.core.compat; + +import net.minecraft.client.gl.CompiledShader; +import net.minecraft.client.gl.ShaderProgram; +import net.minecraft.client.render.VertexFormat; +import net.raphimc.immediatelyfast.injection.interfaces.IShaderProgram; +import org.spongepowered.asm.mixin.Mixin; +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.CallbackInfoReturnable; + +@Mixin(ShaderProgram.class) +public abstract class MixinShaderProgram implements IShaderProgram { + + @Unique + private CompiledShader immediatelyFast$vertexShader; + + @Unique + private CompiledShader immediatelyFast$fragmentShader; + + @Inject(method = "create", at = @At("RETURN")) + private static void storeShaderReferences(CompiledShader vertexShader, CompiledShader fragmentShader, VertexFormat format, CallbackInfoReturnable cir) { + if (cir.getReturnValue() instanceof IShaderProgram mixinShaderProgram) { + mixinShaderProgram.immediatelyFast$setVertexShader(vertexShader); + mixinShaderProgram.immediatelyFast$setFragmentShader(fragmentShader); + } + } + + @Override + public CompiledShader immediatelyFast$getVertexShader() { + return this.immediatelyFast$vertexShader; + } + + @Override + public void immediatelyFast$setVertexShader(final CompiledShader vertexShader) { + this.immediatelyFast$vertexShader = vertexShader; + } + + @Override + public CompiledShader immediatelyFast$getFragmentShader() { + return this.immediatelyFast$fragmentShader; + } + + @Override + public void immediatelyFast$setFragmentShader(final CompiledShader fragmentShader) { + this.immediatelyFast$fragmentShader = fragmentShader; + } + +} diff --git a/common/src/main/resources/immediatelyfast-common.mixins.json b/common/src/main/resources/immediatelyfast-common.mixins.json index 4290247a..9c58116a 100644 --- a/common/src/main/resources/immediatelyfast-common.mixins.json +++ b/common/src/main/resources/immediatelyfast-common.mixins.json @@ -13,6 +13,7 @@ "core.MixinVertexConsumerProvider", "core.MixinWindow", "core.compat.MixinShaderLoader", + "core.compat.MixinShaderProgram", "core.compat.MixinTextDisplayEntityRenderer", "disable_error_checking.MixinGL11", "fast_buffer_upload.MixinVertexBuffer", diff --git a/common/src/main/resources/immediatelyfast.accesswidener b/common/src/main/resources/immediatelyfast.accesswidener index 7a1f69ef..d19c3dc2 100644 --- a/common/src/main/resources/immediatelyfast.accesswidener +++ b/common/src/main/resources/immediatelyfast.accesswidener @@ -4,7 +4,7 @@ accessWidener v1 named accessible class net/minecraft/client/font/TextRenderer$Drawer accessible field net/minecraft/client/MinecraftClient fontManager Lnet/minecraft/client/font/FontManager; accessible field net/minecraft/client/render/entity/feature/WolfCollarFeatureRenderer SKIN Lnet/minecraft/util/Identifier; - +accessible class net/minecraft/client/gl/ShaderLoader$Cache accessible field net/minecraft/client/util/BufferAllocator pointer J accessible field net/minecraft/client/render/BufferBuilder allocator Lnet/minecraft/client/util/BufferAllocator; accessible field net/minecraft/client/render/BufferBuilder building Z @@ -23,5 +23,4 @@ accessible class net/minecraft/client/texture/MapTextureManager$MapTexture accessible field net/minecraft/client/render/VertexConsumerProvider$Immediate layerBuffers Ljava/util/SequencedMap; accessible field net/minecraft/client/gui/DrawContext vertexConsumers Lnet/minecraft/client/render/VertexConsumerProvider$Immediate; mutable field net/minecraft/client/gui/DrawContext vertexConsumers Lnet/minecraft/client/render/VertexConsumerProvider$Immediate; - accessible field com/mojang/blaze3d/systems/RenderSystem shaderLightDirections [Lorg/joml/Vector3f;