From 81e94dc10371975edd24b6bbb9e0657956fe3071 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Thu, 11 Jan 2024 13:47:15 -0500 Subject: [PATCH] Unhardcode vertex format indexes --- .../vertex/VertexFormatDescription.java | 84 +++++++++++++++++++ .../mixin/core/pipeline/MixinBakedQuad.java | 70 ++++++++++++---- .../core/pipeline/MixinUnpackedBakedQuad.java | 18 ++++ src/main/resources/sodium.mixins.json | 1 + 4 files changed, 155 insertions(+), 18 deletions(-) create mode 100644 src/main/java/me/jellysquid/mods/sodium/client/render/vertex/VertexFormatDescription.java create mode 100644 src/main/java/me/jellysquid/mods/sodium/mixin/core/pipeline/MixinUnpackedBakedQuad.java diff --git a/src/main/java/me/jellysquid/mods/sodium/client/render/vertex/VertexFormatDescription.java b/src/main/java/me/jellysquid/mods/sodium/client/render/vertex/VertexFormatDescription.java new file mode 100644 index 000000000..f7792bbf0 --- /dev/null +++ b/src/main/java/me/jellysquid/mods/sodium/client/render/vertex/VertexFormatDescription.java @@ -0,0 +1,84 @@ +package me.jellysquid.mods.sodium.client.render.vertex; + +import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.client.renderer.vertex.VertexFormat; +import net.minecraft.client.renderer.vertex.VertexFormatElement; + +import java.util.Arrays; +import java.util.Map; +import java.util.concurrent.locks.StampedLock; + +/** + * Inspired by modern Sodium's VertexFormatDescription. + */ +public class VertexFormatDescription { + public enum Element { + POSITION(DefaultVertexFormats.POSITION_3F), + COLOR(DefaultVertexFormats.COLOR_4UB), + TEXTURE(DefaultVertexFormats.TEX_2F), + NORMAL(DefaultVertexFormats.NORMAL_3B); + + final VertexFormatElement underlyingElement; + static final Map VANILLA_TO_COMMON = new Reference2ReferenceOpenHashMap<>(); + Element(VertexFormatElement baseElement) { + this.underlyingElement = baseElement; + } + + static { + for(Element e : Element.values()) { + VANILLA_TO_COMMON.put(e.underlyingElement, e); + } + } + } + + private static final Element[] COMMON_ELEMENTS = Element.values(); + + private final int[] elementOffsets; + private final VertexFormat format; + + private static final Map REGISTRY = new Reference2ReferenceOpenHashMap<>(); + private static final StampedLock LOCK = new StampedLock(); + + VertexFormatDescription(VertexFormat format) { + this.elementOffsets = new int[COMMON_ELEMENTS.length]; + Arrays.fill(this.elementOffsets, -1); + this.format = format; + for(int i = 0; i < format.getElementCount(); i++) { + Element commonElement = Element.VANILLA_TO_COMMON.get(format.getElement(i)); + if(commonElement != null) { + elementOffsets[commonElement.ordinal()] = format.getOffset(i) / 4; + } + } + } + + public static VertexFormatDescription get(VertexFormat format) { + long stamp = LOCK.readLock(); + VertexFormatDescription desc; + try { + desc = REGISTRY.get(format); + } finally { + LOCK.unlockRead(stamp); + } + + if (desc != null) { + return desc; + } + + desc = new VertexFormatDescription(format); + + stamp = LOCK.writeLock(); + + try { + REGISTRY.put(format, desc); + } finally { + LOCK.unlockWrite(stamp); + } + + return desc; + } + + public int getIndex(VertexFormatDescription.Element element) { + return this.elementOffsets[element.ordinal()]; + } +} diff --git a/src/main/java/me/jellysquid/mods/sodium/mixin/core/pipeline/MixinBakedQuad.java b/src/main/java/me/jellysquid/mods/sodium/mixin/core/pipeline/MixinBakedQuad.java index 5f63b77b9..849afac32 100644 --- a/src/main/java/me/jellysquid/mods/sodium/mixin/core/pipeline/MixinBakedQuad.java +++ b/src/main/java/me/jellysquid/mods/sodium/mixin/core/pipeline/MixinBakedQuad.java @@ -2,10 +2,12 @@ import me.jellysquid.mods.sodium.client.model.quad.ModelQuadView; import me.jellysquid.mods.sodium.client.model.quad.properties.ModelQuadFlags; +import me.jellysquid.mods.sodium.client.render.vertex.VertexFormatDescription; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.vertex.VertexFormat; import net.minecraft.util.EnumFacing; +import net.minecraftforge.client.model.pipeline.UnpackedBakedQuad; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -13,13 +15,8 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import static me.jellysquid.mods.sodium.client.util.ModelQuadUtil.*; - @Mixin(BakedQuad.class) public class MixinBakedQuad implements ModelQuadView { - @Shadow - @Final - protected int[] vertexData; @Shadow @Final @@ -29,36 +26,61 @@ public class MixinBakedQuad implements ModelQuadView { @Final protected int tintIndex; - private int cachedFlags; + @Shadow public int[] getVertexData() { + throw new AssertionError(); + } + + @Shadow @Final protected VertexFormat format; + protected int cachedFlags; + + private VertexFormatDescription formatDescription; @Inject(method = "([IILnet/minecraft/util/EnumFacing;Lnet/minecraft/client/renderer/texture/TextureAtlasSprite;ZLnet/minecraft/client/renderer/vertex/VertexFormat;)V", at = @At("RETURN")) private void init(int[] vertexData, int colorIndex, EnumFacing face, TextureAtlasSprite sprite, boolean shade, VertexFormat format, CallbackInfo ci) { - this.cachedFlags = ModelQuadFlags.getQuadFlags((BakedQuad) (Object) this); + this.formatDescription = VertexFormatDescription.get(format); + if(!UnpackedBakedQuad.class.isAssignableFrom(this.getClass())) { + this.cachedFlags = ModelQuadFlags.getQuadFlags((BakedQuad) (Object) this); + } + } + + private int vertexOffset(int idx) { + return idx * this.format.getIntegerSize(); } @Override public float getX(int idx) { - return Float.intBitsToFloat(this.vertexData[vertexOffset(idx) + POSITION_INDEX]); + int positionIndex = this.formatDescription.getIndex(VertexFormatDescription.Element.POSITION); + if (positionIndex == -1) { + return 0; + } + return Float.intBitsToFloat(this.getVertexData()[vertexOffset(idx) + positionIndex]); } @Override public float getY(int idx) { - return Float.intBitsToFloat(this.vertexData[vertexOffset(idx) + POSITION_INDEX + 1]); + int positionIndex = this.formatDescription.getIndex(VertexFormatDescription.Element.POSITION); + if (positionIndex == -1) { + return 0; + } + return Float.intBitsToFloat(this.getVertexData()[vertexOffset(idx) + positionIndex + 1]); } @Override public float getZ(int idx) { - return Float.intBitsToFloat(this.vertexData[vertexOffset(idx) + POSITION_INDEX + 2]); + int positionIndex = this.formatDescription.getIndex(VertexFormatDescription.Element.POSITION); + if (positionIndex == -1) { + return 0; + } + return Float.intBitsToFloat(this.getVertexData()[vertexOffset(idx) + positionIndex + 2]); } @Override public int getColor(int idx) { - if(vertexOffset(idx) + COLOR_INDEX < vertexData.length) { - return this.vertexData[vertexOffset(idx) + COLOR_INDEX]; - } else - { - return vertexData.length; + int colorIndex = this.formatDescription.getIndex(VertexFormatDescription.Element.COLOR); + if (colorIndex == -1) { + return 0; } + return this.getVertexData()[vertexOffset(idx) + colorIndex]; } @Override @@ -68,12 +90,20 @@ public int getColor(int idx) { @Override public float getTexU(int idx) { - return Float.intBitsToFloat(this.vertexData[vertexOffset(idx) + TEXTURE_INDEX]); + int textureIndex = this.formatDescription.getIndex(VertexFormatDescription.Element.TEXTURE); + if (textureIndex == -1) { + return 0; + } + return Float.intBitsToFloat(this.getVertexData()[vertexOffset(idx) + textureIndex]); } @Override public float getTexV(int idx) { - return Float.intBitsToFloat(this.vertexData[vertexOffset(idx) + TEXTURE_INDEX + 1]); + int textureIndex = this.formatDescription.getIndex(VertexFormatDescription.Element.TEXTURE); + if (textureIndex == -1) { + return 0; + } + return Float.intBitsToFloat(this.getVertexData()[vertexOffset(idx) + textureIndex + 1]); } @Override @@ -83,7 +113,11 @@ public int getFlags() { @Override public int getNormal(int idx) { - return this.vertexData[vertexOffset(idx) + NORMAL_INDEX]; + int normalIndex = this.formatDescription.getIndex(VertexFormatDescription.Element.NORMAL); + if (normalIndex == -1) { + return 0; + } + return this.getVertexData()[vertexOffset(idx) + normalIndex]; } @Override diff --git a/src/main/java/me/jellysquid/mods/sodium/mixin/core/pipeline/MixinUnpackedBakedQuad.java b/src/main/java/me/jellysquid/mods/sodium/mixin/core/pipeline/MixinUnpackedBakedQuad.java new file mode 100644 index 000000000..4a2a23bdd --- /dev/null +++ b/src/main/java/me/jellysquid/mods/sodium/mixin/core/pipeline/MixinUnpackedBakedQuad.java @@ -0,0 +1,18 @@ +package me.jellysquid.mods.sodium.mixin.core.pipeline; + +import me.jellysquid.mods.sodium.client.model.quad.properties.ModelQuadFlags; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraftforge.client.model.pipeline.UnpackedBakedQuad; +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; + +@Mixin(UnpackedBakedQuad.class) +public class MixinUnpackedBakedQuad { + protected int cachedFlags; + @Inject(method = "", at = @At("RETURN")) + private void calculateFlags(CallbackInfo ci) { + this.cachedFlags = ModelQuadFlags.getQuadFlags((BakedQuad) (Object) this); + } +} diff --git a/src/main/resources/sodium.mixins.json b/src/main/resources/sodium.mixins.json index 0a3574686..23c137663 100644 --- a/src/main/resources/sodium.mixins.json +++ b/src/main/resources/sodium.mixins.json @@ -20,6 +20,7 @@ "core.pipeline.MixinBakedQuad", "core.pipeline.MixinBufferBuilder", "core.pipeline.MixinVertexFormat", + "core.pipeline.MixinUnpackedBakedQuad", "features.block.MixinBlockModelRenderer", "features.block.MixinWorldRenderer", "features.buffer_builder.fast_advance.MixinVertexFormat",