Skip to content

Commit f499c63

Browse files
committed
perf(terrain): cache the vanilla missing-model reference across block renders
MissingModelCompat.isMissingModel walked a four-deep getter chain (Minecraft -> BlockRendererDispatcher -> BlockModelShapes -> ModelManager) for every block render during chunk mesh building. The reference only changes on resource reload, so cache it (volatile, worker-thread safe) and clear the cache from a reload listener registered in Actinium.onInit. The one-argument isMissingModel signature is kept so the compat-bridge renderer bytecode contract is untouched.
1 parent 20e6e73 commit f499c63

2 files changed

Lines changed: 24 additions & 2 deletions

File tree

src/main/java/com/dhj/actinium/Actinium.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.dhj.actinium.compat.chunkanimator.ChunkAnimatorCompat;
44
import com.dhj.actinium.compat.dh.ActiniumDHIrisCompat;
55
import com.dhj.actinium.compat.dh.DistantHorizonsCompat;
6+
import com.dhj.actinium.compat.MissingModelCompat;
67
import com.dhj.actinium.compat.kirino.KirinoCompat;
78
import com.dhj.actinium.compat.neofontrender.NeoFontRenderCompat;
89
import com.dhj.actinium.command.TogglePassCommand;
@@ -28,6 +29,7 @@
2829
import net.coderbot.iris.rendertarget.IRenderTargetExt;
2930
import net.minecraft.client.Minecraft;
3031
import net.minecraft.client.renderer.OpenGlHelper;
32+
import net.minecraft.client.resources.IReloadableResourceManager;
3133
import net.minecraft.launchwrapper.Launch;
3234
import net.minecraftforge.client.ClientCommandHandler;
3335
import net.minecraftforge.client.event.RenderGameOverlayEvent;
@@ -175,6 +177,9 @@ public void onInit(FMLInitializationEvent event) {
175177
ChunkAnimatorCompat.install();
176178
KirinoCompat.install();
177179

180+
((IReloadableResourceManager) Minecraft.getMinecraft().getResourceManager())
181+
.registerReloadListener(resourceManager -> MissingModelCompat.onResourceManagerReload());
182+
178183
if ((Boolean) Launch.blackboard.get("fml.deobfuscatedEnvironment")) {
179184
ClientCommandHandler.instance.registerCommand(new TogglePassCommand());
180185
}

src/main/java/com/dhj/actinium/compat/MissingModelCompat.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,19 @@ public final class MissingModelCompat {
2525
private MissingModelCompat() {
2626
}
2727

28+
/**
29+
* Cached vanilla missing-model reference. Resolving it walks a four-deep getter chain through
30+
* the block renderer dispatcher, which runs per block render during chunk mesh building; the
31+
* reference itself only changes on resource reload, which clears the cache through
32+
* {@link #onResourceManagerReload()}. Volatile because chunk meshes are built on worker threads.
33+
*/
34+
private static volatile IBakedModel cachedMissingModel;
35+
36+
/** Drops the cached missing-model reference so the next check re-resolves it. */
37+
public static void onResourceManagerReload() {
38+
cachedMissingModel = null;
39+
}
40+
2841
/**
2942
* Binary name of Forge's {@code FancyMissingModel.BakedModel}. The class is package-private,
3043
* so its name is matched instead of using {@code instanceof}; it ships with Minecraft Forge.
@@ -55,8 +68,12 @@ private MissingModelCompat() {
5568
* fancy label variant) and must not be rendered from a chunk build worker thread.
5669
*/
5770
public static boolean isMissingModel(IBakedModel model) {
58-
IBakedModel missingModel = Minecraft.getMinecraft().getBlockRendererDispatcher()
59-
.getBlockModelShapes().getModelManager().getMissingModel();
71+
IBakedModel missingModel = cachedMissingModel;
72+
if (missingModel == null) {
73+
missingModel = Minecraft.getMinecraft().getBlockRendererDispatcher()
74+
.getBlockModelShapes().getModelManager().getMissingModel();
75+
cachedMissingModel = missingModel;
76+
}
6077
return isMissingModel(model, missingModel);
6178
}
6279

0 commit comments

Comments
 (0)