From 7bf003be3bf78ebdf59ce07cfab23d2bf147d19e Mon Sep 17 00:00:00 2001 From: Asek3 <64613894+Asek3@users.noreply.github.com> Date: Thu, 7 Sep 2023 22:02:19 +0300 Subject: [PATCH] Some RenderType fixes Co-Authored-By: coderbot Co-Authored-By: IMS --- .../iris/layer/OuterWrappedRenderType.java | 10 ++- .../iris/mixin/MixinLevelRenderer.java | 2 +- .../MixinBlockEntityRenderDispatcher.java | 71 +++++++---------- .../MixinEntityRenderDispatcher.java | 77 ++++--------------- 4 files changed, 54 insertions(+), 106 deletions(-) diff --git a/src/main/java/net/coderbot/iris/layer/OuterWrappedRenderType.java b/src/main/java/net/coderbot/iris/layer/OuterWrappedRenderType.java index be05f8da9b..a212905861 100644 --- a/src/main/java/net/coderbot/iris/layer/OuterWrappedRenderType.java +++ b/src/main/java/net/coderbot/iris/layer/OuterWrappedRenderType.java @@ -14,7 +14,7 @@ public class OuterWrappedRenderType extends RenderType implements WrappableRende private final RenderStateShard extra; private final RenderType wrapped; - public OuterWrappedRenderType(String name, RenderType wrapped, RenderStateShard extra) { + private OuterWrappedRenderType(String name, RenderType wrapped, RenderStateShard extra) { super(name, wrapped.format(), wrapped.mode(), wrapped.bufferSize(), wrapped.affectsCrumbling(), shouldSortOnUpload(wrapped), wrapped::setupRenderState, wrapped::clearRenderState); @@ -22,6 +22,14 @@ public OuterWrappedRenderType(String name, RenderType wrapped, RenderStateShard this.wrapped = wrapped; } + public static OuterWrappedRenderType wrapExactlyOnce(String name, RenderType wrapped, RenderStateShard extra) { + if (wrapped instanceof OuterWrappedRenderType) { + wrapped = ((OuterWrappedRenderType) wrapped).unwrap(); + } + + return new OuterWrappedRenderType(name, wrapped, extra); + } + @Override public void setupRenderState() { extra.setupRenderState(); diff --git a/src/main/java/net/coderbot/iris/mixin/MixinLevelRenderer.java b/src/main/java/net/coderbot/iris/mixin/MixinLevelRenderer.java index 4d8ad5f924..54df901987 100644 --- a/src/main/java/net/coderbot/iris/mixin/MixinLevelRenderer.java +++ b/src/main/java/net/coderbot/iris/mixin/MixinLevelRenderer.java @@ -210,7 +210,7 @@ public class MixinLevelRenderer { to = @At(value = "INVOKE", target = "net/minecraft/client/renderer/LevelRenderer.renderHitOutline (Lcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/blaze3d/vertex/VertexConsumer;Lnet/minecraft/world/entity/Entity;DDDLnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)V") )) private RenderType iris$beginBlockOutline(RenderType type) { - return new OuterWrappedRenderType("iris:is_outline", type, IsOutlineRenderStateShard.INSTANCE); + return OuterWrappedRenderType.wrapExactlyOnce("iris:is_outline", type, IsOutlineRenderStateShard.INSTANCE); } @Inject(method = "renderLevel", at = @At(value = "CONSTANT", args = "stringValue=translucent")) diff --git a/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinBlockEntityRenderDispatcher.java b/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinBlockEntityRenderDispatcher.java index 43cb0d9dcd..130632e515 100644 --- a/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinBlockEntityRenderDispatcher.java +++ b/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinBlockEntityRenderDispatcher.java @@ -1,15 +1,8 @@ package net.coderbot.iris.mixin.entity_render_context; -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.CallbackInfo; - -import com.mojang.blaze3d.vertex.PoseStack; - import it.unimi.dsi.fastutil.objects.Object2IntMap; +import net.coderbot.batchedentityrendering.impl.Groupable; import net.coderbot.iris.block_rendering.BlockRenderingSettings; -import net.coderbot.iris.fantastic.WrappingMultiBufferSource; import net.coderbot.iris.layer.BlockEntityRenderStateShard; import net.coderbot.iris.layer.OuterWrappedRenderType; import net.minecraft.client.renderer.MultiBufferSource; @@ -17,6 +10,9 @@ import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; /** * Wraps block entity rendering functions in order to create additional render layers @@ -25,57 +21,44 @@ */ @Mixin(BlockEntityRenderDispatcher.class) public class MixinBlockEntityRenderDispatcher { - private static final String RENDER = - "render(Lnet/minecraft/block/entity/BlockEntity;FLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;)V"; - - private static final String RUN_REPORTED = - "Lnet/minecraft/client/renderer/blockentity/BlockEntityRenderDispatcher;tryRender(Lnet/minecraft/world/level/block/entity/BlockEntity;Ljava/lang/Runnable;)V"; // I inject here in the method so that: // // 1. we can know that some checks we need have already been done - // 2. if someone cancels this method hopefully it gets cancelled before this point - @Inject(method = "render", at = @At(value = "INVOKE", target = RUN_REPORTED)) - private void iris$beforeRender(BlockEntity blockEntity, float tickDelta, PoseStack poseStack, - MultiBufferSource bufferSource, CallbackInfo ci) { - if (!(bufferSource instanceof WrappingMultiBufferSource)) { - return; + // 2. if someone cancels this method hopefully it gets cancelled before this point, so we + // aren't running any redundant computations. + // + // NOTE: This is the last location that we can inject at, because the MultiBufferSource variable gets + // captured by the lambda shortly afterwards, and therefore our ModifyVariable call becomes ineffective! + @ModifyVariable(method = "render", at = @At(value = "INVOKE", + target = "net/minecraft/world/level/block/entity/BlockEntityType.isValid (Lnet/minecraft/world/level/block/Block;)Z"), + allow = 1, require = 1) + private MultiBufferSource iris$wrapBufferSource(MultiBufferSource bufferSource, BlockEntity blockEntity) { + if (!(bufferSource instanceof Groupable)) { + // Fully batched entity rendering is not being used, do not use this wrapper!!! + return bufferSource; } Object2IntMap blockStateIds = BlockRenderingSettings.INSTANCE.getBlockStateIds(); if (blockStateIds == null) { - return; + return bufferSource; } // At this point, based on where we are in BlockEntityRenderDispatcher: // - The block entity is non-null // - The block entity has a world - // - The block entity thinks that it's supported by a valid block - - int intId = blockStateIds.getOrDefault(blockEntity.getBlockState(), -1); - RenderStateShard stateShard = BlockEntityRenderStateShard.forId(intId); + // - The block entity is not sure that it's supported by a valid block - ((WrappingMultiBufferSource) bufferSource).pushWrappingFunction(type -> - new OuterWrappedRenderType("iris:is_block_entity", type, stateShard)); - } - - @Inject(method = "render", at = @At(value = "INVOKE", target = RUN_REPORTED, shift = At.Shift.AFTER)) - private void iris$afterRender(BlockEntity blockEntity, float tickDelta, PoseStack matrix, - MultiBufferSource bufferSource, CallbackInfo ci) { - if (!(bufferSource instanceof WrappingMultiBufferSource)) { - return; + BlockState state = blockEntity.getBlockState(); + if (!blockEntity.getType().isValid(state.getBlock())) { + return bufferSource; } - // This might not get called if we crash and something like NotEnoughCrashes tries - // to act like nothing happened. - // - // Supporting that is hard so I decided to just ignore that for now. - // - // This might also not get called if a different mod cancels before runReported but - // after my inject, but I placed my inject there in the hopes that it would - // not be likely to be affected by a cancel. I hope that the universe doesn't - // conspire against me and cause that to break. - ((WrappingMultiBufferSource) bufferSource).popWrappingFunction(); + int intId = blockStateIds.getOrDefault(state, -1); + RenderStateShard stateShard = BlockEntityRenderStateShard.forId(intId); + + return type -> + bufferSource.getBuffer(OuterWrappedRenderType.wrapExactlyOnce("iris:is_block_entity", type, stateShard)); } -} +} \ No newline at end of file diff --git a/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinEntityRenderDispatcher.java b/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinEntityRenderDispatcher.java index 36b839063e..d094ce88a9 100644 --- a/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinEntityRenderDispatcher.java +++ b/src/main/java/net/coderbot/iris/mixin/entity_render_context/MixinEntityRenderDispatcher.java @@ -1,24 +1,20 @@ package net.coderbot.iris.mixin.entity_render_context; -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.CallbackInfo; - -import com.mojang.blaze3d.vertex.PoseStack; - import it.unimi.dsi.fastutil.objects.Object2IntFunction; +import net.coderbot.batchedentityrendering.impl.Groupable; import net.coderbot.iris.block_rendering.BlockRenderingSettings; -import net.coderbot.iris.fantastic.WrappingMultiBufferSource; import net.coderbot.iris.layer.EntityRenderStateShard; import net.coderbot.iris.layer.OuterWrappedRenderType; import net.coderbot.iris.shaderpack.materialmap.NamespacedId; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderStateShard; import net.minecraft.client.renderer.entity.EntityRenderDispatcher; +import net.minecraft.core.Registry; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.Entity; -import net.minecraftforge.registries.ForgeRegistries; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; /** * Wraps entity rendering functions in order to create additional render layers @@ -27,66 +23,27 @@ */ @Mixin(EntityRenderDispatcher.class) public class MixinEntityRenderDispatcher { - private static final String CRASHREPORT_CREATE = - "Lnet/minecraft/world/entity/Entity;fillCrashReportCategory(Lnet/minecraft/CrashReportCategory;)V"; - - // Inject after MatrixStack#push to increase the chances that we won't be caught out by a poorly-positioned - // cancellation in an inject. - @Inject(method = "render", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;pushPose()V", shift = At.Shift.AFTER)) - private void iris$beginEntityRender(Entity entity, double x, double y, double z, float yaw, float tickDelta, - PoseStack poseStack, MultiBufferSource bufferSource, int light, - CallbackInfo ci) { - if (!(bufferSource instanceof WrappingMultiBufferSource)) { - return; + // Inject after MatrixStack#push since at this point we know that most cancellation checks have already passed. + @ModifyVariable(method = "render", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;pushPose()V", shift = At.Shift.AFTER), + allow = 1, require = 1) + private MultiBufferSource iris$beginEntityRender(MultiBufferSource bufferSource, Entity entity) { + if (!(bufferSource instanceof Groupable)) { + // Fully batched entity rendering is not being used, do not use this wrapper!!! + return bufferSource; } - ResourceLocation entityId = ForgeRegistries.ENTITIES.getKey(entity.getType()); + ResourceLocation entityId = Registry.ENTITY_TYPE.getKey(entity.getType()); Object2IntFunction entityIds = BlockRenderingSettings.INSTANCE.getEntityIds(); if (entityIds == null) { - return; + return bufferSource; } int intId = entityIds.applyAsInt(new NamespacedId(entityId.getNamespace(), entityId.getPath())); RenderStateShard phase = EntityRenderStateShard.forId(intId); - ((WrappingMultiBufferSource) bufferSource).pushWrappingFunction(layer -> - new OuterWrappedRenderType("iris:is_entity", layer, phase)); - } - - // Inject before MatrixStack#pop so that our wrapper stack management operations naturally line up - // with vanilla's MatrixStack management functions. - @Inject(method = "render", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;popPose()V")) - private void iris$endEntityRender(Entity entity, double x, double y, double z, float yaw, float tickDelta, - PoseStack poseStack, MultiBufferSource bufferSource, int light, - CallbackInfo ci) { - if (!(bufferSource instanceof WrappingMultiBufferSource)) { - return; - } - - ((WrappingMultiBufferSource) bufferSource).popWrappingFunction(); - } - - @Inject(method = "render", at = @At(value = "INVOKE", target = CRASHREPORT_CREATE)) - private void iris$crashedEntityRender(Entity entity, double x, double y, double z, float yaw, float tickDelta, - PoseStack poseStack, MultiBufferSource bufferSource, int light, - CallbackInfo ci) { - if (!(bufferSource instanceof WrappingMultiBufferSource)) { - return; - } - - try { - // Try to avoid leaving the wrapping stack in a bad state if we crash. - // This will only be an issue with mods like NotEnoughCrashes that try - // to act like nothing happened when a fatal error occurs. - // - // This could fail if we crash before MatrixStack#push, but this is mostly - // a best-effort thing, it doesn't have to work perfectly. NEC will cause - // weird chaos no matter what we do. - ((WrappingMultiBufferSource) bufferSource).popWrappingFunction(); - } catch (Exception e) { - // oh well, we're gonna crash anyways. - } + return type -> + bufferSource.getBuffer(OuterWrappedRenderType.wrapExactlyOnce("iris:is_entity", type, phase)); } -} +} \ No newline at end of file