Skip to content

Commit 8ac6e43

Browse files
committed
feat: Texture optimizations support for animated swansong PBR textures
1 parent 965f13b commit 8ac6e43

File tree

7 files changed

+248
-4
lines changed

7 files changed

+248
-4
lines changed

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ dependencies {
165165
compileOnly("org.joml:joml:1.10.8")
166166
compileOnly("it.unimi.dsi:fastutil:8.5.16")
167167
compileOnly("mega:megatraceservice:1.2.0")
168-
compileOnly("com.ventooth:swansong-mc1.7.10:1.2.1:dev")
168+
compileOnly("com.ventooth:swansong-mc1.7.10:1.2.5:dev")
169169
compileOnly("maven.modrinth:etfuturum:2.6.2:dev")
170170
add(panamaNatives.compileOnlyConfigurationName, "com.falsepattern:zanama-rt:0.2.0")
171171

src/main/java/com/falsepattern/falsetweaks/FalseTweaks.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@
4747
guiFactory = Tags.ROOT_PKG + ".config.FalseTweaksGuiFactory",
4848
acceptableRemoteVersions = "*",
4949
dependencies = "required-after:falsepatternlib@[1.9.1,);" +
50-
"after:gtnhlib@[0.5.21,);")
50+
"after:gtnhlib@[0.5.21,);" +
51+
"after:swansong@[1.2.5,);")
5152
public class FalseTweaks {
5253

5354
@SidedProxy(clientSide = Tags.ROOT_PKG + ".proxy.ClientProxy",

src/main/java/com/falsepattern/falsetweaks/mixin/mixins/client/animfix/TextureMap_CommonMixin.java

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,15 @@
2222

2323
package com.falsepattern.falsetweaks.mixin.mixins.client.animfix;
2424

25+
import com.falsepattern.falsetweaks.Compat;
2526
import com.falsepattern.falsetweaks.api.animfix.IAnimationUpdateBatcher;
2627
import com.falsepattern.falsetweaks.modules.animfix.AnimationUpdateBatcherRegistry;
2728
import com.falsepattern.falsetweaks.modules.animfix.interfaces.ITextureMapMixin;
2829
import lombok.Getter;
2930
import org.spongepowered.asm.mixin.Final;
3031
import org.spongepowered.asm.mixin.Mixin;
3132
import org.spongepowered.asm.mixin.Shadow;
33+
import org.spongepowered.asm.mixin.Unique;
3234
import org.spongepowered.asm.mixin.injection.At;
3335
import org.spongepowered.asm.mixin.injection.Inject;
3436
import org.spongepowered.asm.mixin.injection.Redirect;
@@ -49,6 +51,20 @@ public abstract class TextureMap_CommonMixin implements ITextureMapMixin {
4951
private String basePath;
5052
@Getter
5153
private IAnimationUpdateBatcher batcher;
54+
@Unique
55+
private IAnimationUpdateBatcher ft$batcherNorm;
56+
@Unique
57+
private IAnimationUpdateBatcher ft$batcherSpec;
58+
59+
@Override
60+
public IAnimationUpdateBatcher ft$getBatcherNorm() {
61+
return ft$batcherNorm;
62+
}
63+
64+
@Override
65+
public IAnimationUpdateBatcher ft$getBatcherSpec() {
66+
return ft$batcherSpec;
67+
}
5268

5369
@Inject(method = "loadTexture",
5470
at = @At(value = "HEAD"),
@@ -90,7 +106,30 @@ private boolean storeAnimatedInBatch(List<TextureAtlasSprite> listAnimatedSprite
90106
public void initializeBatcher(int xOffset, int yOffset, int width, int height) {
91107
if (batcher != null) {
92108
batcher.terminate();
109+
batcher = null;
110+
}
111+
if (ft$batcherNorm != null) {
112+
ft$batcherNorm.terminate();
113+
ft$batcherNorm = null;
114+
}
115+
if (ft$batcherSpec != null) {
116+
ft$batcherSpec.terminate();
117+
ft$batcherSpec = null;
118+
}
119+
if (width * height > 0) {
120+
batcher = AnimationUpdateBatcherRegistry.newBatcher(xOffset, yOffset, width, height, mipmapLevels);
121+
if (Compat.swanSongInstalled()) {
122+
ft$batcherNorm = AnimationUpdateBatcherRegistry.newBatcher(xOffset,
123+
yOffset,
124+
width,
125+
height,
126+
mipmapLevels);
127+
ft$batcherSpec = AnimationUpdateBatcherRegistry.newBatcher(xOffset,
128+
yOffset,
129+
width,
130+
height,
131+
mipmapLevels);
132+
}
93133
}
94-
batcher = AnimationUpdateBatcherRegistry.newBatcher(xOffset, yOffset, width, height, mipmapLevels);
95134
}
96135
}

src/main/java/com/falsepattern/falsetweaks/mixin/mixins/client/animfix/TextureMap_UnprofiledMixin.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@
3131

3232
import net.minecraft.client.renderer.texture.TextureMap;
3333

34-
@Mixin(TextureMap.class)
34+
@Mixin(value = TextureMap.class,
35+
priority = 1100) // Swansong compat)
3536
public abstract class TextureMap_UnprofiledMixin implements ITextureMapMixin {
3637

3738
@Inject(method = "updateAnimations",
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
/*
2+
* This file is part of FalseTweaks.
3+
*
4+
* Copyright (C) 2022-2025 FalsePattern
5+
* All Rights Reserved
6+
*
7+
* The above copyright notice and this permission notice shall be included
8+
* in all copies or substantial portions of the Software.
9+
*
10+
* FalseTweaks is free software: you can redistribute it and/or modify
11+
* it under the terms of the GNU Lesser General Public License as published by
12+
* the Free Software Foundation, only version 3 of the License.
13+
*
14+
* FalseTweaks is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* GNU Lesser General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU Lesser General Public License
20+
* along with FalseTweaks. If not, see <https://www.gnu.org/licenses/>.
21+
*/
22+
23+
package com.falsepattern.falsetweaks.mixin.mixins.client.animfix.swansong;
24+
25+
import com.falsepattern.falsetweaks.api.animfix.IAnimationUpdateBatcher;
26+
import com.falsepattern.falsetweaks.modules.animfix.AnimationUpdateBatcherRegistry;
27+
import com.falsepattern.falsetweaks.modules.animfix.interfaces.ITextureMapMixin;
28+
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
29+
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
30+
import com.llamalad7.mixinextras.sugar.Local;
31+
import com.llamalad7.mixinextras.sugar.Share;
32+
import com.llamalad7.mixinextras.sugar.ref.LocalRef;
33+
import com.ventooth.swansong.mixin.interfaces.PBRTextureHolder;
34+
import com.ventooth.swansong.pbr.PBRTextureEngine;
35+
import it.unimi.dsi.fastutil.objects.ObjectList;
36+
import lombok.val;
37+
import org.spongepowered.asm.mixin.Mixin;
38+
import org.spongepowered.asm.mixin.injection.At;
39+
import org.spongepowered.asm.mixin.injection.Inject;
40+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
41+
42+
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
43+
import net.minecraft.client.renderer.texture.TextureMap;
44+
45+
@Mixin(value = PBRTextureEngine.class,
46+
remap = false)
47+
public abstract class PBRTextureEngineMixin {
48+
@WrapOperation(method = "uploadAtlasSpritesAll",
49+
at = @At(value = "INVOKE",
50+
target = "Lcom/ventooth/swansong/pbr/PBRTextureEngine;uploadAtlasSpriteLayer(ILit/unimi/dsi/fastutil/objects/ObjectList;IIII)V",
51+
ordinal = 0),
52+
require = 1)
53+
private static void uploadNorm(int glName,
54+
ObjectList<TextureAtlasSprite> sprites,
55+
int width,
56+
int height,
57+
int mipLevels,
58+
int defaultCol,
59+
Operation<Void> original,
60+
@Local(argsOnly = true) PBRTextureHolder map) {
61+
AnimationUpdateBatcherRegistry.batcher = ((ITextureMapMixin)map).ft$getBatcherNorm();
62+
original.call(glName, sprites, width, height, mipLevels, defaultCol);
63+
AnimationUpdateBatcherRegistry.batcher = null;
64+
}
65+
66+
@WrapOperation(method = "uploadAtlasSpritesAll",
67+
at = @At(value = "INVOKE",
68+
target = "Lcom/ventooth/swansong/pbr/PBRTextureEngine;uploadAtlasSpriteLayer(ILit/unimi/dsi/fastutil/objects/ObjectList;IIII)V",
69+
ordinal = 1),
70+
require = 1)
71+
private static void uploadSpec(int glName,
72+
ObjectList<TextureAtlasSprite> sprites,
73+
int width,
74+
int height,
75+
int mipLevels,
76+
int defaultCol,
77+
Operation<Void> original,
78+
@Local(argsOnly = true) PBRTextureHolder map) {
79+
AnimationUpdateBatcherRegistry.batcher = ((ITextureMapMixin)map).ft$getBatcherSpec();
80+
original.call(glName, sprites, width, height, mipLevels, defaultCol);
81+
AnimationUpdateBatcherRegistry.batcher = null;
82+
}
83+
84+
@WrapOperation(method = "uploadAtlasSpritesAll",
85+
at = @At(value = "INVOKE",
86+
target = "Lcom/ventooth/swansong/pbr/PBRTextureEngine;uploadAtlasSpriteLayer(ILit/unimi/dsi/fastutil/objects/ObjectList;IIII)V",
87+
ordinal = 2),
88+
require = 1)
89+
private static void uploadBase(int glName,
90+
ObjectList<TextureAtlasSprite> sprites,
91+
int width,
92+
int height,
93+
int mipLevels,
94+
int defaultCol,
95+
Operation<Void> original,
96+
@Local(argsOnly = true) PBRTextureHolder map) {
97+
AnimationUpdateBatcherRegistry.batcher = ((ITextureMapMixin)map).getBatcher();
98+
original.call(glName, sprites, width, height, mipLevels, defaultCol);
99+
AnimationUpdateBatcherRegistry.batcher = null;
100+
}
101+
102+
@Inject(method = "uploadAtlasSpriteLayer",
103+
at = @At(value = "INVOKE",
104+
target = "Ljava/lang/Math;min(II)I"),
105+
require = 1)
106+
private static void uploadAnimated(CallbackInfo ci,
107+
@Local TextureAtlasSprite sprite) {
108+
if (AnimationUpdateBatcherRegistry.batcher != null && sprite.hasAnimationMetadata()) {
109+
AnimationUpdateBatcherRegistry.batcher.scheduleUpload(sprite.getFrameTextureData(0),
110+
sprite.getIconWidth(),
111+
sprite.getIconHeight(),
112+
sprite.getOriginX(),
113+
sprite.getOriginY());
114+
}
115+
}
116+
117+
@WrapOperation(method = "uploadAtlasSpriteLayer",
118+
at = @At(value = "INVOKE",
119+
target = "Lnet/minecraft/client/renderer/texture/TextureUtil;uploadTextureMipmap([[IIIIIZZ)V",
120+
remap = true),
121+
require = 1)
122+
private static void dontScheduleNonAnimated(int[][] texture,
123+
int width,
124+
int height,
125+
int xOffset,
126+
int yOffset,
127+
boolean a,
128+
boolean b,
129+
Operation<Void> original) {
130+
val batch = AnimationUpdateBatcherRegistry.batcher;
131+
AnimationUpdateBatcherRegistry.batcher = null;
132+
original.call(texture, width, height, xOffset, yOffset, a, b);
133+
AnimationUpdateBatcherRegistry.batcher = batch;
134+
}
135+
136+
@Inject(method = "updateAnimations",
137+
at = @At("HEAD"),
138+
require = 1)
139+
private static void preUpdateAnimations(CallbackInfo ci,
140+
@Local(argsOnly = true) TextureMap map,
141+
@Share("baseBatcher")LocalRef<IAnimationUpdateBatcher> baseBatcher) {
142+
baseBatcher.set(AnimationUpdateBatcherRegistry.batcher);
143+
AnimationUpdateBatcherRegistry.batcher = null;
144+
}
145+
146+
@Inject(method = "updateAnimations",
147+
at = @At(value = "INVOKE",
148+
target = "Lcom/ventooth/swansong/sufrace/PBRTexture2D;bind()V",
149+
ordinal = 0),
150+
require = 1)
151+
private static void preUpdateNorm(CallbackInfo ci,
152+
@Local(argsOnly = true) TextureMap map) {
153+
AnimationUpdateBatcherRegistry.batcher = ((ITextureMapMixin)map).ft$getBatcherNorm();
154+
}
155+
156+
@Inject(method = "updateAnimations",
157+
at = @At(value = "INVOKE",
158+
target = "Lcom/ventooth/swansong/sufrace/PBRTexture2D;bind()V",
159+
ordinal = 1),
160+
require = 1)
161+
private static void preUpdateSpec(CallbackInfo ci,
162+
@Local(argsOnly = true) TextureMap map) {
163+
val b = AnimationUpdateBatcherRegistry.batcher;
164+
if (b != null) {
165+
b.upload();
166+
}
167+
AnimationUpdateBatcherRegistry.batcher = ((ITextureMapMixin)map).ft$getBatcherSpec();
168+
}
169+
170+
@Inject(method = "updateAnimations",
171+
at = @At(value = "INVOKE",
172+
target = "Lnet/minecraft/client/renderer/texture/TextureUtil;bindTexture(I)V",
173+
remap = true),
174+
require = 1)
175+
private static void preUpdateResetTex(CallbackInfo ci) {
176+
val b = AnimationUpdateBatcherRegistry.batcher;
177+
if (b != null) {
178+
b.upload();
179+
}
180+
}
181+
182+
@Inject(method = "updateAnimations",
183+
at = @At("RETURN"),
184+
require = 1)
185+
private static void postUpdateAnimations(CallbackInfo ci,
186+
@Share("baseBatcher")LocalRef<IAnimationUpdateBatcher> baseBatcher) {
187+
AnimationUpdateBatcherRegistry.batcher = baseBatcher.get();
188+
}
189+
}

src/main/java/com/falsepattern/falsetweaks/mixin/plugin/standard/Mixin.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,10 @@ public enum Mixin implements IMixins {
293293
"animfix.fastcraft.DynamicTextureMixin",
294294
"animfix.fastcraft.TextureMapMixin",
295295
"animfix.fastcraft.TextureUtilMixin")),
296+
AnimFix_SwanSong(Phase.EARLY,
297+
() -> ModuleConfig.TEXTURE_OPTIMIZATIONS,
298+
require(SwanSong),
299+
client("animfix.swansong.PBRTextureEngineMixin")),
296300

297301
Voxelizer(Phase.EARLY,
298302
() -> ModuleConfig.VOXELIZER,

src/main/java/com/falsepattern/falsetweaks/modules/animfix/interfaces/ITextureMapMixin.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,14 @@ public interface ITextureMapMixin {
2828
void initializeBatcher(int offsetX, int offsetY, int width, int height);
2929

3030
IAnimationUpdateBatcher getBatcher();
31+
32+
/**
33+
* Only valid when swansong is present
34+
*/
35+
IAnimationUpdateBatcher ft$getBatcherNorm();
36+
37+
/**
38+
* Only valid when swansong is present
39+
*/
40+
IAnimationUpdateBatcher ft$getBatcherSpec();
3141
}

0 commit comments

Comments
 (0)