Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

optimize adding normals #52

Merged
merged 2 commits into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ This work, "PolyPatcher", is adapted from ["Patcher"](https://sk1er.club/mods/pa
- Boost performance by reducing quad counts in item models
- Boost performance by decreasing size of sine and cosine lookup tables
- Boost performance by only rendering special tile entities once instead of twice per frame
- Boost performance by optimizing adding normals to vertex formats
- Boost performance by unloading tile entities quickly
- Improve speed when changing language, mipmap level, and anisotropic filtering level
- Fix Forge held item lighting to match vanilla
Expand Down
20 changes: 20 additions & 0 deletions src/main/java/club/sk1er/patcher/hooks/VertexLighterFlatHook.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package club.sk1er.patcher.hooks;

import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.renderer.vertex.VertexFormatElement;

public class VertexLighterFlatHook {
private static final VertexFormatElement NORMAL_4F = new VertexFormatElement(0, VertexFormatElement.EnumType.FLOAT, VertexFormatElement.EnumUsage.NORMAL, 4);
private static final VertexFormat BLOCK_WITH_NORMAL = withNormalUncached(DefaultVertexFormats.BLOCK);

public static VertexFormat withNormal(VertexFormat format) {
if (format == DefaultVertexFormats.BLOCK) return BLOCK_WITH_NORMAL;
return withNormalUncached(format);
}

private static VertexFormat withNormalUncached(VertexFormat format) {
if (format == null || format.hasNormal()) return format;
return new VertexFormat(format).addElement(NORMAL_4F);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@
@SuppressWarnings("unused")
public interface IVertexLighterFlat {
BlockInfo getBlockInfo();

void resetBlockInfo();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package club.sk1er.patcher.mixins.performance.forge;

import club.sk1er.patcher.hooks.VertexLighterFlatHook;
import com.google.common.cache.LoadingCache;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.renderer.vertex.VertexFormatElement;
import net.minecraftforge.client.model.pipeline.LightUtil;
import org.apache.commons.lang3.tuple.Pair;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import static net.minecraftforge.client.model.pipeline.LightUtil.mapFormats;

@Mixin(value = LightUtil.class, remap = false)
public abstract class LightUtilMixin_OptimizeNormals {
//#if MC==10809
@Unique
private static final ConcurrentMap<Pair<VertexFormat, VertexFormat>, int[]> patcher$FORMAT_MAPS = new ConcurrentHashMap<>();
@Unique
private static final VertexFormat patcher$DEFAULT_FROM = VertexLighterFlatHook.withNormal(DefaultVertexFormats.BLOCK);
@Unique
private static final VertexFormat patcher$DEFAULT_TO = DefaultVertexFormats.ITEM;
@Unique
private static final int[] patcher$DEFAULT_MAPPING = patcher$generateMapping(patcher$DEFAULT_FROM, patcher$DEFAULT_TO);

@SuppressWarnings("UnstableApiUsage")
@Redirect(method = "putBakedQuad", at = @At(value = "INVOKE", target = "Lcom/google/common/cache/LoadingCache;getUnchecked(Ljava/lang/Object;)Ljava/lang/Object;"))
private static <K, V> V patcher$getUnchecked(LoadingCache<K, V> instance, K k) {
return (V) mapFormats((VertexFormat) k, DefaultVertexFormats.ITEM);
}

// @Inject(method = "mapFormats", at = @At("HEAD"), cancellable = true)
// private static void patcher$fasterMapFormats(VertexFormat from, VertexFormat to, CallbackInfoReturnable<int[]> cir) {
// if (from.equals(patcher$DEFAULT_FROM) && to.equals(patcher$DEFAULT_TO)) {
// cir.setReturnValue(patcher$DEFAULT_MAPPING);
// return;
// }
// cir.setReturnValue(patcher$FORMAT_MAPS.computeIfAbsent(Pair.of(from, to), pair -> patcher$generateMapping(pair.getLeft(), pair.getRight())));
// }

/**
* @author MicrocontrollersDev
* @reason the above inject doesnt work
*/
@Overwrite
public static int[] mapFormats(VertexFormat from, VertexFormat to) {
if (from.equals(patcher$DEFAULT_FROM) && to.equals(patcher$DEFAULT_TO)) return patcher$DEFAULT_MAPPING;
return patcher$FORMAT_MAPS.computeIfAbsent(Pair.of(from, to), pair -> patcher$generateMapping(pair.getLeft(), pair.getRight()));
}

@Unique
private static int[] patcher$generateMapping(VertexFormat from, VertexFormat to) {
int fromCount = from.getElementCount();
int toCount = to.getElementCount();
int[] eMap = new int[fromCount];

for(int e = 0; e < fromCount; e++) {
VertexFormatElement expected = from.getElement(e);
int e2;
for(e2 = 0; e2 < toCount; e2++) {
VertexFormatElement current = to.getElement(e2);
if(expected.getUsage() == current.getUsage() && expected.getIndex() == current.getIndex()) {
break;
}
}
eMap[e] = e2;
}
return eMap;
}
//#endif
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package club.sk1er.patcher.mixins.performance.forge;

import club.sk1er.patcher.hooks.VertexLighterFlatHook;
import club.sk1er.patcher.hooks.accessors.IVertexLighterFlat;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraftforge.client.model.pipeline.IVertexConsumer;
import net.minecraftforge.client.model.pipeline.QuadGatheringTransformer;
import net.minecraftforge.client.model.pipeline.VertexLighterFlat;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import java.util.Objects;

@Mixin(value = VertexLighterFlat.class, remap = false)
public abstract class VertexLighterFlatMixin_OptimizeNormals extends QuadGatheringTransformer implements IVertexLighterFlat {
//#if MC==10809
@Unique
protected VertexFormat patcher$baseFormat;
@Shadow
protected int posIndex;
@Shadow
protected int normalIndex;
@Shadow
protected int colorIndex;
@Shadow
protected int lightmapIndex;

@Inject(method = "setParent", at = @At("HEAD"), cancellable = true)
private void patcher$optimizeSetParent(IVertexConsumer parent, CallbackInfo ci) {
super.setParent(parent);
setVertexFormat(parent.getVertexFormat());
ci.cancel();
}

@Override
public void setVertexFormat(VertexFormat format) {
if (Objects.equals(format,patcher$baseFormat)) return;
this.patcher$baseFormat = format;
super.setVertexFormat(VertexLighterFlatHook.withNormal(format));
for (int i = 0; i < getVertexFormat().getElementCount(); i++) {
switch (getVertexFormat().getElement(i).getUsage()) {
case POSITION:
posIndex = i;
break;
case NORMAL:
normalIndex = i;
break;
case COLOR:
colorIndex = i;
break;
case UV:
if (getVertexFormat().getElement(i).getIndex() == 1) {
lightmapIndex = i;
}
break;
default:
}
}
if (posIndex == -1) {
throw new IllegalArgumentException("vertex lighter needs format with position");
}
if (lightmapIndex == -1) {
throw new IllegalArgumentException("vertex lighter needs format with lightmap");
}
if (colorIndex == -1) {
throw new IllegalArgumentException("vertex lighter needs format with color");
}
}
//#endif
}
2 changes: 2 additions & 0 deletions src/main/resources/mixins.patcher.json
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,10 @@
"performance.forge.FMLControlledNamespacedRegistryMixin_TrimAvailabilityMap",
"performance.forge.ItemLayerModelMixin_ReduceQuadCount",
"performance.forge.JarDiscovererMixin_ReplaceRegex",
"performance.forge.LightUtilMixin_OptimizeNormals",
"performance.forge.ModDiscovererMixin_Logging",
"performance.forge.ModDiscovererMixin_ReplaceRegex",
"performance.forge.VertexLighterFlatMixin_OptimizeNormals",
"performance.hudcaching.EntityRendererMixin_HUDCaching",
"performance.hudcaching.FramebufferMixin_HUDCaching",
"performance.hudcaching.GlStateManagerMixin_HUDCaching",
Expand Down
Loading