Pārlūkot izejas kodu

New: deduplicate vertex data of baked quads used in SimpleBakedModels
The restrictions is based on the hope that if anyone is modifying quad data in practice, they aren't doing it with quads in standard model implementations

malte0811 4 gadi atpakaļ
vecāks
revīzija
c84166b435

+ 2 - 1
build.gradle

@@ -1,7 +1,7 @@
 import java.util.stream.Collectors
 
 plugins {
-    id "architectury-plugin" version "2.0.65"
+    id "architectury-plugin" version "2.0.66"
     id "forgified-fabric-loom" version "0.6.59" apply false
 }
 
@@ -18,6 +18,7 @@ subprojects {
             "mrl",
             "dedupmultipart",
             "blockstatecache",
+            "dedupbakedquad",
         ].stream()
         .map({s -> rootProject.archives_base_name+"."+s+".mixin.json"})
         .collect(Collectors.toList())

+ 26 - 0
common/src/main/java/malte0811/ferritecore/hash/LambdaBasedHash.java

@@ -0,0 +1,26 @@
+package malte0811.ferritecore.hash;
+
+import it.unimi.dsi.fastutil.Hash;
+
+import java.util.function.BiPredicate;
+import java.util.function.ToIntFunction;
+
+public class LambdaBasedHash<T> implements Hash.Strategy<T> {
+    private final ToIntFunction<T> hash;
+    private final BiPredicate<T, T> equal;
+
+    public LambdaBasedHash(ToIntFunction<T> hash, BiPredicate<T, T> equal) {
+        this.hash = hash;
+        this.equal = equal;
+    }
+
+    @Override
+    public int hashCode(T o) {
+        return hash.applyAsInt(o);
+    }
+
+    @Override
+    public boolean equals(T a, T b) {
+        return equal.test(a, b);
+    }
+}

+ 17 - 0
common/src/main/java/malte0811/ferritecore/impl/Deduplicator.java

@@ -1,8 +1,12 @@
 package malte0811.ferritecore.impl;
 
 import com.mojang.datafixers.util.Unit;
+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap;
+import malte0811.ferritecore.hash.LambdaBasedHash;
+import malte0811.ferritecore.mixin.dedupbakedquad.BakedQuadAccess;
 import net.minecraft.block.BlockState;
 import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.model.BakedQuad;
 import net.minecraft.client.renderer.model.IBakedModel;
 import net.minecraft.client.renderer.model.MultipartBakedModel;
 import net.minecraft.client.resources.ReloadListener;
@@ -11,6 +15,7 @@ import net.minecraft.resources.IReloadableResourceManager;
 import net.minecraft.resources.IResourceManager;
 import org.apache.commons.lang3.tuple.Pair;
 
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
@@ -23,6 +28,9 @@ public class Deduplicator {
     private static final Map<List<Pair<Predicate<BlockState>, IBakedModel>>, MultipartBakedModel> KNOWN_MULTIPART_MODELS = new ConcurrentHashMap<>();
     private static final Map<List<Predicate<BlockState>>, Predicate<BlockState>> OR_PREDICATE_CACHE = new ConcurrentHashMap<>();
     private static final Map<List<Predicate<BlockState>>, Predicate<BlockState>> AND_PREDICATE_CACHE = new ConcurrentHashMap<>();
+    private static final Object2ObjectOpenCustomHashMap<int[], int[]> BAKED_QUAD_CACHE = new Object2ObjectOpenCustomHashMap<>(
+            new LambdaBasedHash<>(Arrays::hashCode, Arrays::equals)
+    );
 
     public static String deduplicateVariant(String variant) {
         return VARIANT_IDENTITIES.computeIfAbsent(variant, Function.identity());
@@ -46,6 +54,13 @@ public class Deduplicator {
         );
     }
 
+    public static void deduplicate(BakedQuad bq) {
+        synchronized (BAKED_QUAD_CACHE) {
+            int[] deduped = BAKED_QUAD_CACHE.computeIfAbsent(bq.getVertexData(), Function.identity());
+            ((BakedQuadAccess) bq).setVertexData(deduped);
+        }
+    }
+
     public static void registerReloadListener() {
         // Register the reload listener s.t. its "sync" part runs after the model loader reload
         ((IReloadableResourceManager) Minecraft.getInstance().getResourceManager()).addReloadListener(new ReloadListener<Unit>() {
@@ -60,6 +75,8 @@ public class Deduplicator {
                 KNOWN_MULTIPART_MODELS.clear();
                 OR_PREDICATE_CACHE.clear();
                 AND_PREDICATE_CACHE.clear();
+                BAKED_QUAD_CACHE.clear();
+                BAKED_QUAD_CACHE.trim();
             }
         });
     }

+ 9 - 9
common/src/main/java/malte0811/ferritecore/mixin/config/FerriteConfig.java

@@ -1,16 +1,11 @@
 package malte0811.ferritecore.mixin.config;
 
-import it.unimi.dsi.fastutil.objects.Object2BooleanMap;
-import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap;
-import malte0811.ferritecore.ModMain;
-
 import javax.annotation.Nullable;
-import java.io.IOException;
 import java.lang.reflect.Method;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
 import java.util.function.Predicate;
 
 public class FerriteConfig {
@@ -20,6 +15,7 @@ public class FerriteConfig {
     public static final Option MRL_CACHE;
     public static final Option DEDUP_MULTIPART;
     public static final Option DEDUP_BLOCKSTATE_CACHE;
+    public static final Option DEDUP_QUADS;
 
     static {
         ConfigBuilder builder = new ConfigBuilder();
@@ -48,6 +44,10 @@ public class FerriteConfig {
                 "blockstateCacheDeduplication",
                 "Deduplicate cached data for blockstates, most importantly collision and render shapes"
         );
+        DEDUP_QUADS = builder.createOption(
+                "bakedQuadDeduplication",
+                "Deduplicate vertex data of baked quads in the basic model implementations"
+        );
         builder.finish();
     }
 

+ 13 - 0
common/src/main/java/malte0811/ferritecore/mixin/dedupbakedquad/BakedQuadAccess.java

@@ -0,0 +1,13 @@
+package malte0811.ferritecore.mixin.dedupbakedquad;
+
+import net.minecraft.client.renderer.model.BakedQuad;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Mutable;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+@Mixin(BakedQuad.class)
+public interface BakedQuadAccess {
+    @Accessor
+    @Mutable
+    void setVertexData(int[] newVertexData);
+}

+ 19 - 0
common/src/main/java/malte0811/ferritecore/mixin/dedupbakedquad/Config.java

@@ -0,0 +1,19 @@
+package malte0811.ferritecore.mixin.dedupbakedquad;
+
+import com.google.common.collect.ImmutableList;
+import malte0811.ferritecore.mixin.config.FerriteConfig;
+import malte0811.ferritecore.mixin.config.FerriteMixinConfig;
+
+import java.util.List;
+
+public class Config extends FerriteMixinConfig {
+    @Override
+    protected List<String> getAllMixins() {
+        return ImmutableList.of("SimpleModelBuilderMixin", "BakedQuadAccess");
+    }
+
+    @Override
+    protected boolean isEnabled(String mixin) {
+        return FerriteConfig.DEDUP_QUADS.isEnabled();
+    }
+}

+ 25 - 0
common/src/main/java/malte0811/ferritecore/mixin/dedupbakedquad/SimpleModelBuilderMixin.java

@@ -0,0 +1,25 @@
+package malte0811.ferritecore.mixin.dedupbakedquad;
+
+import malte0811.ferritecore.impl.Deduplicator;
+import net.minecraft.client.renderer.model.BakedQuad;
+import net.minecraft.client.renderer.model.SimpleBakedModel;
+import net.minecraft.util.Direction;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
+
+@Mixin(SimpleBakedModel.Builder.class)
+public class SimpleModelBuilderMixin {
+    @Inject(method = "addGeneralQuad", at = @At("HEAD"))
+    public void deduplicate(BakedQuad quad, CallbackInfoReturnable<SimpleBakedModel.Builder> cir) {
+        Deduplicator.deduplicate(quad);
+    }
+
+    @Inject(method = "addFaceQuad", at = @At("HEAD"))
+    public void deduplicate(
+            Direction direction, BakedQuad quad, CallbackInfoReturnable<SimpleBakedModel.Builder> cir
+    ) {
+        Deduplicator.deduplicate(quad);
+    }
+}

+ 16 - 0
common/src/main/resources/ferritecore.dedupbakedquad.mixin.json

@@ -0,0 +1,16 @@
+{
+  "required": true,
+  "package": "malte0811.ferritecore.mixin.dedupbakedquad",
+  "compatibilityLevel": "JAVA_8",
+  "refmap": "ferritecore-common-refmap.json",
+  "injectors": {
+    "defaultRequire": 1
+  },
+  "minVersion": "0.8",
+  "plugin": "malte0811.ferritecore.mixin.dedupbakedquad.Config",
+  "client": [
+    "BakedQuadAccess",
+    "SimpleModelBuilderMixin"
+  ],
+  "mixins": []
+}

+ 1 - 2
common/src/main/resources/ferritecore.dedupmultipart.mixin.json

@@ -11,6 +11,5 @@
   "client": [
     "MixinMultipartBuilder"
   ],
-  "mixins": [
-  ]
+  "mixins": []
 }

+ 1 - 0
fabric/src/main/resources/fabric.mod.json

@@ -21,6 +21,7 @@
     "ferritecore.fastmap.mixin.json",
     "ferritecore.mrl.mixin.json",
     "ferritecore.predicates.mixin.json",
+    "ferritecore.dedupbakedquad.mixin.json",
     "ferritecore.fabric.mixin.json"
   ]
 }