From 882f4832dfa222760c90953263efaf510146674d Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sun, 9 Apr 2023 14:03:32 -0400 Subject: [PATCH] Allow concurrent retrieval of models from the cache --- .../dynamic_resources/ModelBakeryMixin.java | 96 ++++++++++--------- 1 file changed, 53 insertions(+), 43 deletions(-) diff --git a/src/main/java/org/embeddedt/modernfix/mixin/perf/dynamic_resources/ModelBakeryMixin.java b/src/main/java/org/embeddedt/modernfix/mixin/perf/dynamic_resources/ModelBakeryMixin.java index 56522a38..e965131e 100644 --- a/src/main/java/org/embeddedt/modernfix/mixin/perf/dynamic_resources/ModelBakeryMixin.java +++ b/src/main/java/org/embeddedt/modernfix/mixin/perf/dynamic_resources/ModelBakeryMixin.java @@ -236,67 +236,77 @@ public abstract class ModelBakeryMixin { * @reason synchronize */ @Overwrite - public synchronized UnbakedModel getModel(ResourceLocation modelLocation) { + public UnbakedModel getModel(ResourceLocation modelLocation) { if(modelLocation.equals(MISSING_MODEL_LOCATION)) return missingModel; - if (this.unbakedCache.containsKey(modelLocation)) { - return this.unbakedCache.get(modelLocation); - } else if (this.loadingStack.contains(modelLocation)) { - throw new IllegalStateException("Circular reference while loading " + modelLocation); + UnbakedModel existing = this.unbakedCache.get(modelLocation); + if (existing != null) { + return existing; } else { - this.loadingStack.add(modelLocation); - UnbakedModel iunbakedmodel = missingModel; + synchronized(this) { + if (this.loadingStack.contains(modelLocation)) { + throw new IllegalStateException("Circular reference while loading " + modelLocation); + } else { + this.loadingStack.add(modelLocation); + UnbakedModel iunbakedmodel = missingModel; - while(!this.loadingStack.isEmpty()) { - ResourceLocation resourcelocation = this.loadingStack.iterator().next(); + while(!this.loadingStack.isEmpty()) { + ResourceLocation resourcelocation = this.loadingStack.iterator().next(); - try { - if (!this.unbakedCache.containsKey(resourcelocation)) { - if(debugDynamicModelLoading) - LOGGER.info("Loading {}", resourcelocation); - this.loadModel(resourcelocation); + try { + if (!this.unbakedCache.containsKey(resourcelocation)) { + if(debugDynamicModelLoading) + LOGGER.info("Loading {}", resourcelocation); + this.loadModel(resourcelocation); + // TODO: in theory the cache can get evicted right here and we lose the model + // very unlikely to occur though + } + } catch (ModelBakery.BlockStateDefinitionException var9) { + LOGGER.warn(var9.getMessage()); + this.unbakedCache.put(resourcelocation, iunbakedmodel); + } catch (Exception var10) { + LOGGER.warn("Unable to load model: '{}' referenced from: {}: {}", resourcelocation, modelLocation, var10); + this.unbakedCache.put(resourcelocation, iunbakedmodel); + } finally { + this.loadingStack.remove(resourcelocation); + } } - } catch (ModelBakery.BlockStateDefinitionException var9) { - LOGGER.warn(var9.getMessage()); - this.unbakedCache.put(resourcelocation, iunbakedmodel); - } catch (Exception var10) { - LOGGER.warn("Unable to load model: '{}' referenced from: {}: {}", resourcelocation, modelLocation, var10); - this.unbakedCache.put(resourcelocation, iunbakedmodel); - } finally { - this.loadingStack.remove(resourcelocation); + + return this.unbakedCache.getOrDefault(modelLocation, iunbakedmodel); } } - - return this.unbakedCache.getOrDefault(modelLocation, iunbakedmodel); } } @Overwrite - public synchronized BakedModel getBakedModel(ResourceLocation arg, ModelState arg2, Function textureGetter) { + public BakedModel getBakedModel(ResourceLocation arg, ModelState arg2, Function textureGetter) { Triple triple = Triple.of(arg, arg2.getRotation(), arg2.isUvLocked()); - if (this.bakedCache.containsKey(triple)) { - return this.bakedCache.get(triple); + BakedModel existing = this.bakedCache.get(triple); + if (existing != null) { + return existing; } else if (this.atlasSet == null) { throw new IllegalStateException("bake called too early"); } else { - if(debugDynamicModelLoading) - LOGGER.info("Baking {}", arg); - UnbakedModel iunbakedmodel = this.getModel(arg); - iunbakedmodel.getMaterials(this::getModel, new HashSet<>()); - BakedModel ibakedmodel = null; - if (iunbakedmodel instanceof BlockModel) { - BlockModel blockmodel = (BlockModel)iunbakedmodel; - if (blockmodel.getRootModel() == GENERATION_MARKER) { - ibakedmodel = ITEM_MODEL_GENERATOR.generateBlockModel(textureGetter, blockmodel).bake((ModelBakery)(Object)this, blockmodel, this.atlasSet::getSprite, arg2, arg, false); + synchronized (this) { + if(debugDynamicModelLoading) + LOGGER.info("Baking {}", arg); + UnbakedModel iunbakedmodel = this.getModel(arg); + iunbakedmodel.getMaterials(this::getModel, new HashSet<>()); + BakedModel ibakedmodel = null; + if (iunbakedmodel instanceof BlockModel) { + BlockModel blockmodel = (BlockModel)iunbakedmodel; + if (blockmodel.getRootModel() == GENERATION_MARKER) { + ibakedmodel = ITEM_MODEL_GENERATOR.generateBlockModel(textureGetter, blockmodel).bake((ModelBakery)(Object)this, blockmodel, this.atlasSet::getSprite, arg2, arg, false); + } } + if(ibakedmodel == null) { + ibakedmodel = iunbakedmodel.bake((ModelBakery) (Object) this, textureGetter, arg2, arg); + } + DynamicModelBakeEvent event = new DynamicModelBakeEvent(arg, iunbakedmodel, ibakedmodel, (ModelLoader)(Object)this); + ModLoader.get().postEvent(event); + this.bakedCache.put(triple, event.getModel()); + return event.getModel(); } - if(ibakedmodel == null) { - ibakedmodel = iunbakedmodel.bake((ModelBakery) (Object) this, textureGetter, arg2, arg); - } - DynamicModelBakeEvent event = new DynamicModelBakeEvent(arg, iunbakedmodel, ibakedmodel, (ModelLoader)(Object)this); - ModLoader.get().postEvent(event); - this.bakedCache.put(triple, event.getModel()); - return event.getModel(); } } }