Add more locking in various vanilla model loading paths

This commit is contained in:
embeddedt 2025-01-24 09:32:06 -05:00
parent 6706656623
commit 74a339bc2c
No known key found for this signature in database
GPG Key ID: A69433EC199B5613
5 changed files with 79 additions and 6 deletions

View File

@ -1,11 +1,17 @@
package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources; package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources;
import com.llamalad7.mixinextras.injector.ModifyReturnValue; import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.ModelBakery; import net.minecraft.client.resources.model.ModelBakery;
import net.minecraft.client.resources.model.ModelState;
import net.minecraft.client.resources.model.UnbakedModel; import net.minecraft.client.resources.model.UnbakedModel;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import org.embeddedt.modernfix.ModernFix; import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.duck.IExtendedModelBakery;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;
@ -16,6 +22,7 @@ import org.spongepowered.asm.mixin.injection.At;
public abstract class ModelBakerImplMixin { public abstract class ModelBakerImplMixin {
@Shadow public abstract UnbakedModel getModel(ResourceLocation location); @Shadow public abstract UnbakedModel getModel(ResourceLocation location);
@Shadow @Final private ModelBakery field_40571;
@Unique @Unique
private int mfix$getDepth = 0; private int mfix$getDepth = 0;
@ -36,4 +43,15 @@ public abstract class ModelBakerImplMixin {
mfix$getDepth--; mfix$getDepth--;
return model; return model;
} }
@WrapMethod(method = "bake(Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/client/resources/model/ModelState;)Lnet/minecraft/client/resources/model/BakedModel;")
private BakedModel mfix$lockWhenBaking(ResourceLocation location, ModelState transform, Operation<BakedModel> original) {
var lock = ((IExtendedModelBakery)this.field_40571).mfix$getLock();
lock.lock();
try {
return original.call(location, transform);
} finally {
lock.unlock();
}
}
} }

View File

@ -1,6 +1,7 @@
package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources; package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
@ -108,6 +109,16 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery {
} }
} }
@WrapMethod(method = "getModel")
private UnbakedModel mfix$lockWhenGettingModel(ResourceLocation modelLocation, Operation<UnbakedModel> original) {
modelBakeryLock.lock();
try {
return original.call(modelLocation);
} finally {
modelBakeryLock.unlock();
}
}
@Override @Override
public UnbakedModel mfix$getMissingModel() { public UnbakedModel mfix$getMissingModel() {
return missingModel; return missingModel;
@ -199,10 +210,26 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery {
private static final int MAXIMUM_CACHE_SIZE = 1000; private static final int MAXIMUM_CACHE_SIZE = 1000;
private void runCleanup() { private void runCleanup() {
((LRUMap<?, ?>)this.unbakedCache).dropEntriesToMeetSize(MAXIMUM_CACHE_SIZE); try {
((LRUMap<?, ?>)this.bakedCache).dropEntriesToMeetSize(MAXIMUM_CACHE_SIZE); ((LRUMap<?, ?>)this.unbakedCache).dropEntriesToMeetSize(MAXIMUM_CACHE_SIZE);
((LRUMap<?, ?>)this.topLevelModels).dropEntriesToMeetSize(MAXIMUM_CACHE_SIZE); } catch(RuntimeException e) {
((LRUMap<?, ?>)this.bakedTopLevelModels).dropEntriesToMeetSize(MAXIMUM_CACHE_SIZE); throw new IllegalStateException("Exception dropping entries in unbaked cache", e);
}
try {
((LRUMap<?, ?>)this.bakedCache).dropEntriesToMeetSize(MAXIMUM_CACHE_SIZE);
} catch(RuntimeException e) {
throw new IllegalStateException("Exception dropping entries in baked cache", e);
}
try {
((LRUMap<?, ?>)this.topLevelModels).dropEntriesToMeetSize(MAXIMUM_CACHE_SIZE);
} catch(RuntimeException e) {
throw new IllegalStateException("Exception dropping entries in top level models", e);
}
try {
((LRUMap<?, ?>)this.bakedTopLevelModels).dropEntriesToMeetSize(MAXIMUM_CACHE_SIZE);
} catch(RuntimeException e) {
throw new IllegalStateException("Exception dropping entries in baked top level models", e);
}
} }
@Override @Override
@ -235,4 +262,9 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery {
public Map<ModelResourceLocation, BakedModel> getBakedTopLevelModels() { public Map<ModelResourceLocation, BakedModel> getBakedTopLevelModels() {
return this.mfix$emulatedBakedRegistry; return this.mfix$emulatedBakedRegistry;
} }
@Override
public ReentrantLock mfix$getLock() {
return this.modelBakeryLock;
}
} }

View File

@ -3,9 +3,12 @@ package org.embeddedt.modernfix.duck;
import net.minecraft.client.resources.model.ModelResourceLocation; import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.client.resources.model.UnbakedModel; import net.minecraft.client.resources.model.UnbakedModel;
import java.util.concurrent.locks.ReentrantLock;
public interface IExtendedModelBakery { public interface IExtendedModelBakery {
void mfix$tick(); void mfix$tick();
void mfix$finishLoading(); void mfix$finishLoading();
UnbakedModel mfix$loadUnbakedModelDynamic(ModelResourceLocation location); UnbakedModel mfix$loadUnbakedModelDynamic(ModelResourceLocation location);
UnbakedModel mfix$getMissingModel(); UnbakedModel mfix$getMissingModel();
ReentrantLock mfix$getLock();
} }

View File

@ -7,7 +7,7 @@ mixinextras_version=0.4.1
mod_id=modernfix mod_id=modernfix
minecraft_version=1.21.1 minecraft_version=1.21.1
enabled_platforms=fabric,neoforge enabled_platforms=fabric,neoforge
forge_version=21.1.15 forge_version=21.1.111
parchment_version=2024.07.07 parchment_version=2024.07.07
parchment_mc_version=1.21 parchment_mc_version=1.21
refined_storage_version=4392788 refined_storage_version=4392788

View File

@ -1,8 +1,15 @@
package org.embeddedt.modernfix.neoforge.mixin.perf.dynamic_resources; package org.embeddedt.modernfix.neoforge.mixin.perf.dynamic_resources;
import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.Material;
import net.minecraft.client.resources.model.ModelBakery; import net.minecraft.client.resources.model.ModelBakery;
import net.minecraft.client.resources.model.ModelResourceLocation; import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.client.resources.model.ModelState;
import net.minecraft.client.resources.model.UnbakedModel; import net.minecraft.client.resources.model.UnbakedModel;
import net.minecraft.resources.ResourceLocation;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.duck.IExtendedModelBakery; import org.embeddedt.modernfix.duck.IExtendedModelBakery;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
@ -10,7 +17,9 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
@Mixin(targets = {"net/minecraft/client/resources/model/ModelBakery$ModelBakerImpl"}) import java.util.function.Function;
@Mixin(ModelBakery.ModelBakerImpl.class)
@ClientOnlyMixin @ClientOnlyMixin
public class ModelBakerImplMixin { public class ModelBakerImplMixin {
@Shadow @Final private ModelBakery field_40571; @Shadow @Final private ModelBakery field_40571;
@ -25,4 +34,15 @@ public class ModelBakerImplMixin {
UnbakedModel model = bakery.mfix$loadUnbakedModelDynamic(location); UnbakedModel model = bakery.mfix$loadUnbakedModelDynamic(location);
return model == bakery.mfix$getMissingModel() ? null : model; return model == bakery.mfix$getMissingModel() ? null : model;
} }
@WrapMethod(method = "bake(Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/client/resources/model/ModelState;Ljava/util/function/Function;)Lnet/minecraft/client/resources/model/BakedModel;", remap = false)
private BakedModel mfix$lockWhenBaking(ResourceLocation location, ModelState transform, Function<Material, TextureAtlasSprite> textureGetter, Operation<BakedModel> original) {
var lock = ((IExtendedModelBakery)this.field_40571).mfix$getLock();
lock.lock();
try {
return original.call(location, transform, textureGetter);
} finally {
lock.unlock();
}
}
} }