Skip to content

Commit

Permalink
optimize mixins
Browse files Browse the repository at this point in the history
  • Loading branch information
FalsePattern committed Nov 27, 2023
1 parent 6471cff commit 00d62c9
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import com.falsepattern.falsetweaks.Tags;
import com.falsepattern.falsetweaks.asm.modules.occlusion.optifine.RenderGlobalDeOptimizer;
import com.falsepattern.falsetweaks.asm.modules.threadedupdates.Threading_RenderBlocksASM;
import com.falsepattern.falsetweaks.config.ModuleConfig;
import com.falsepattern.lib.asm.IClassNodeTransformer;
import com.falsepattern.lib.asm.SmartTransformer;
Expand All @@ -40,5 +41,11 @@ public class FalseTweaksTransformer implements SmartTransformer {
public static RenderGlobalDeOptimizer OPTIFINE_DEOPTIMIZER = new RenderGlobalDeOptimizer();
public static final List<IClassNodeTransformer> TRANSFORMERS = new ArrayList<>(Arrays.asList(OPTIFINE_DEOPTIMIZER));

static {
if (ModuleConfig.THREADED_CHUNK_UPDATES()) {
TRANSFORMERS.add(new Threading_RenderBlocksASM());
}
}

private final List<IClassNodeTransformer> transformers = TRANSFORMERS;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.falsepattern.falsetweaks.asm.modules.threadedupdates;

import com.falsepattern.lib.asm.ASMUtil;
import com.falsepattern.lib.asm.IClassNodeTransformer;
import lombok.val;
import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FrameNode;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.JumpInsnNode;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.VarInsnNode;

public class Threading_RenderBlocksASM implements IClassNodeTransformer {
@Override
public String getName() {
return "Threading_RenderBlocksASM";
}

@Override
public boolean shouldTransform(ClassNode cn, String transformedName, boolean obfuscated) {
return "net.minecraft.client.renderer.RenderBlocks".equals(transformedName);
}

@Override
public void transform(ClassNode cn, String transformedName, boolean obfuscated) {
transformRenderBlockByRenderType(cn);
}

/**
* CallbackInfoReturnable spam avoidance, we need to cancel but this method is called so frequently that the memory
* spam is significant.
*/
private void transformRenderBlockByRenderType(ClassNode cn) {
val method = ASMUtil.findMethodFromMCP(cn, "renderBlockByRenderType", "(Lnet/minecraft/block/Block;III)Z", false);
val list = method.instructions.iterator();
boolean found = false;
while (list.hasNext()) {
val insn = list.next();
if (!(insn instanceof VarInsnNode))
continue;
val varInsn = (VarInsnNode) insn;
if (varInsn.getOpcode() != Opcodes.ISTORE || varInsn.var != 5)
continue;
found = true;
break;
}
if (!found)
throw new IllegalStateException("Could not find injection point!");

list.add(new VarInsnNode(Opcodes.ALOAD, 0));
list.add(new VarInsnNode(Opcodes.ALOAD, 1));
list.add(new VarInsnNode(Opcodes.ILOAD, 5));
list.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "net/minecraft/client/renderer/RenderBlocks", "ft$cancelRenderDelegatedToDifferentThread", "(Lnet/minecraft/block/Block;I)I", false));
val lbl = new LabelNode();
list.add(new InsnNode(Opcodes.DUP));
list.add(new JumpInsnNode(Opcodes.IFEQ, lbl));
list.add(new InsnNode(Opcodes.ICONST_1));
list.add(new InsnNode(Opcodes.ISUB));
list.add(new InsnNode(Opcodes.IRETURN));
list.add(lbl);
list.add(new InsnNode(Opcodes.POP));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,14 @@

import com.falsepattern.falsetweaks.api.ThreadedChunkUpdates;
import com.falsepattern.falsetweaks.modules.threadedupdates.IRendererUpdateResultHolder;
import com.falsepattern.falsetweaks.modules.threadedupdates.OptiFineCompat;
import com.falsepattern.falsetweaks.modules.threadedupdates.ThreadedChunkUpdateHelper;
import lombok.val;
import org.spongepowered.asm.mixin.Mixin;
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.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;

import net.minecraft.block.Block;
import net.minecraft.client.renderer.RenderBlocks;
Expand All @@ -36,13 +35,12 @@

@Mixin(RenderBlocks.class)
public abstract class RenderBlocksMixin {

@Inject(method = "renderBlockByRenderType",
at = @At(value = "INVOKE",
target = "Lnet/minecraft/block/Block;setBlockBoundsBasedOnState(Lnet/minecraft/world/IBlockAccess;III)V"),
cancellable = true,
locals = LocalCapture.CAPTURE_FAILHARD)
private void cancelRenderDelegatedToDifferentThread(Block block, int x, int y, int z, CallbackInfoReturnable<Boolean> cir, int renderType) {
/**
* Called by ASM
*/
@SuppressWarnings("unused")
@Unique
private int ft$cancelRenderDelegatedToDifferentThread(Block block, int renderType) {
int pass = ForgeHooksClient.getWorldRenderPass();
boolean mainThread = Thread.currentThread() == ThreadedChunkUpdateHelper.MAIN_THREAD;

Expand All @@ -51,15 +49,13 @@ private void cancelRenderDelegatedToDifferentThread(Block block, int x, int y, i
val task = ((IRendererUpdateResultHolder) ThreadedChunkUpdateHelper.lastWorldRenderer).ft$getRendererUpdateTask();

if (task != null && !task.cancelled && renderableOffThread && pass >= 0) {
cir.setReturnValue(task.result[pass].renderedSomething);
return task.result[pass].renderedSomething ? 2 : 1;
}
} else if (!renderableOffThread) {
cir.setReturnValue(false);
return 1;
}

if (cir.isCancelled()) {
OptiFineCompat.popEntity();
}
return 0;
}

@Inject(method = "renderBlockByRenderType",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,55 @@ private boolean crackFixOff() {
@Shadow
public abstract boolean hasOverrideBlockTexture();

private IFaceRenderer fr$renderFaceYNeg;
private IFaceRenderer fr$renderFaceYPos;
private IFaceRenderer fr$renderFaceZNeg;
private IFaceRenderer fr$renderFaceZPos;
private IFaceRenderer fr$renderFaceXNeg;
private IFaceRenderer fr$renderFaceXPos;

@Inject(method = {"<init>()V", "<init>(Lnet/minecraft/world/IBlockAccess;)V"},
at = @At("RETURN"),
require = 2)
private void setupCallbacks(CallbackInfo ci) {
fr$renderFaceYNeg = new IFaceRenderer() {
@Override
public void render(Block block, int x, int y, int z, IIcon icon) {
renderFaceYNeg(block, x, y, z, icon);
}
};
fr$renderFaceYPos = new IFaceRenderer() {
@Override
public void render(Block block, int x, int y, int z, IIcon icon) {
renderFaceYPos(block, x, y, z, icon);
}
};
fr$renderFaceZNeg = new IFaceRenderer() {
@Override
public void render(Block block, int x, int y, int z, IIcon icon) {
renderFaceZNeg(block, x, y, z, icon);
}
};
fr$renderFaceZPos = new IFaceRenderer() {
@Override
public void render(Block block, int x, int y, int z, IIcon icon) {
renderFaceZPos(block, x, y, z, icon);
}
};
fr$renderFaceXNeg = new IFaceRenderer() {
@Override
public void render(Block block, int x, int y, int z, IIcon icon) {
renderFaceXNeg(block, x, y, z, icon);
}
};
fr$renderFaceXPos = new IFaceRenderer() {
@Override
public void render(Block block, int x, int y, int z, IIcon icon) {
renderFaceXPos(block, x, y, z, icon);
}
};
}

@Shadow
public abstract void renderFaceYNeg(Block p_147768_1_, double p_147768_2_, double p_147768_4_, double p_147768_6_, IIcon p_147768_8_);

Expand Down Expand Up @@ -531,12 +580,12 @@ public boolean renderWithAO(Block block, int x, int y, int z, float r, float g,
}
state.set(block, x, y, z, r, g, b, useColor, light);
boolean drewSomething;
drewSomething = renderFace(this::renderFaceYNeg, Facing.YNEG);
drewSomething |= renderFace(this::renderFaceYPos, Facing.YPOS);
drewSomething |= renderFace(this::renderFaceZNeg, Facing.ZNEG);
drewSomething |= renderFace(this::renderFaceZPos, Facing.ZPOS);
drewSomething |= renderFace(this::renderFaceXNeg, Facing.XNEG);
drewSomething |= renderFace(this::renderFaceXPos, Facing.XPOS);
drewSomething = renderFace(fr$renderFaceYNeg, Facing.YNEG);
drewSomething |= renderFace(fr$renderFaceYPos, Facing.YPOS);
drewSomething |= renderFace(fr$renderFaceZNeg, Facing.ZNEG);
drewSomething |= renderFace(fr$renderFaceZPos, Facing.ZPOS);
drewSomething |= renderFace(fr$renderFaceXNeg, Facing.XNEG);
drewSomething |= renderFace(fr$renderFaceXPos, Facing.XPOS);

this.enableAO = false;
if (drewSomething && enableMultiRenderReuse) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import com.falsepattern.falsetweaks.modules.triangulator.interfaces.ITessellatorMixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
Expand All @@ -29,12 +30,13 @@

@Mixin(Tessellator.class)
public abstract class TessellatorBSPSortingMixin implements ITessellatorMixin {
@Inject(method = "getVertexState",
at = @At(value = "HEAD"),
cancellable = true,
require = 1)
private void bspSort(float p_147564_1_, float p_147564_2_, float p_147564_3_, CallbackInfoReturnable<TesselatorVertexState> cir) {
cir.setReturnValue(getVertexStateBSP(p_147564_1_, p_147564_2_, p_147564_3_));
/**
* @author FalsePattern
* @reason BSP sorting, way less allocs than inject/cancel
*/
@Overwrite
public TesselatorVertexState getVertexState(float p_147564_1_, float p_147564_2_, float p_147564_3_) {
return getVertexStateBSP(p_147564_1_, p_147564_2_, p_147564_3_);
}

@Inject(method = "setVertexState",
Expand Down

0 comments on commit 00d62c9

Please sign in to comment.