From bb412fc7cb2f8456be81f41891c87ce154df70e2 Mon Sep 17 00:00:00 2001 From: The Judge Date: Sun, 31 Mar 2024 16:10:28 -0700 Subject: [PATCH] Revert "Revert "Apply BufferBuilder optimizations via delegate (#2241)"" This reverts commit 362122241f87a1de1ceae71d254c08d1cabf081a. --- .../format/VertexFormatDescription.java | 5 + .../vertex/VertexFormatDescriptionImpl.java | 25 ++ .../vertex/buffer/ExtendedBufferBuilder.java | 15 + .../vertex/buffer/SodiumBufferBuilder.java | 334 ++++++++++++++++ .../consumer/BufferBuilderMixin.java | 376 +----------------- .../VertexConsumerProviderImmediateMixin.java | 34 ++ src/main/resources/sodium.mixins.json | 1 + 7 files changed, 436 insertions(+), 354 deletions(-) create mode 100644 src/main/java/me/jellysquid/mods/sodium/client/render/vertex/buffer/ExtendedBufferBuilder.java create mode 100644 src/main/java/me/jellysquid/mods/sodium/client/render/vertex/buffer/SodiumBufferBuilder.java create mode 100644 src/main/java/me/jellysquid/mods/sodium/mixin/core/render/immediate/consumer/VertexConsumerProviderImmediateMixin.java diff --git a/src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/VertexFormatDescription.java b/src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/VertexFormatDescription.java index 9b8aa661c2..66d7a3d338 100644 --- a/src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/VertexFormatDescription.java +++ b/src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/VertexFormatDescription.java @@ -28,4 +28,9 @@ public interface VertexFormatDescription { * start at the byte offset (index * stride). */ int stride(); + + /** + * Returns whether or not the format is "simple" (has no duplicate elements). + */ + boolean isSimpleFormat(); } diff --git a/src/main/java/me/jellysquid/mods/sodium/client/render/vertex/VertexFormatDescriptionImpl.java b/src/main/java/me/jellysquid/mods/sodium/client/render/vertex/VertexFormatDescriptionImpl.java index eb93054a34..1fa17d9db7 100644 --- a/src/main/java/me/jellysquid/mods/sodium/client/render/vertex/VertexFormatDescriptionImpl.java +++ b/src/main/java/me/jellysquid/mods/sodium/client/render/vertex/VertexFormatDescriptionImpl.java @@ -4,8 +4,10 @@ import net.caffeinemc.mods.sodium.api.vertex.attributes.CommonVertexAttribute; import net.caffeinemc.mods.sodium.api.vertex.format.VertexFormatDescription; import net.minecraft.client.render.VertexFormat; +import net.minecraft.client.render.VertexFormats; import java.util.Arrays; +import java.util.EnumSet; import java.util.NoSuchElementException; public class VertexFormatDescriptionImpl implements VertexFormatDescription { @@ -14,11 +16,29 @@ public class VertexFormatDescriptionImpl implements VertexFormatDescription { private final int[] offsets; + private final boolean isSimple; + public VertexFormatDescriptionImpl(VertexFormat format, int id) { this.id = id; this.stride = format.getVertexSizeByte(); this.offsets = getOffsets(format); + this.isSimple = checkSimple(format); + } + + private static boolean checkSimple(VertexFormat format) { + EnumSet attributeSet = EnumSet.noneOf(CommonVertexAttribute.class); + var elementList = format.getElements(); + + for (int elementIndex = 0; elementIndex < elementList.size(); elementIndex++) { + var element = elementList.get(elementIndex); + var commonType = CommonVertexAttribute.getCommonType(element); + if (element != VertexFormats.PADDING_ELEMENT && (commonType == null || !attributeSet.add(commonType))) { + return false; + } + } + + return true; } public static int[] getOffsets(VertexFormat format) { @@ -66,4 +86,9 @@ public int id() { public int stride() { return this.stride; } + + @Override + public boolean isSimpleFormat() { + return this.isSimple; + } } diff --git a/src/main/java/me/jellysquid/mods/sodium/client/render/vertex/buffer/ExtendedBufferBuilder.java b/src/main/java/me/jellysquid/mods/sodium/client/render/vertex/buffer/ExtendedBufferBuilder.java new file mode 100644 index 0000000000..5caf3d12ef --- /dev/null +++ b/src/main/java/me/jellysquid/mods/sodium/client/render/vertex/buffer/ExtendedBufferBuilder.java @@ -0,0 +1,15 @@ +package me.jellysquid.mods.sodium.client.render.vertex.buffer; + +import net.caffeinemc.mods.sodium.api.vertex.buffer.VertexBufferWriter; +import net.caffeinemc.mods.sodium.api.vertex.format.VertexFormatDescription; + +import java.nio.ByteBuffer; + +public interface ExtendedBufferBuilder extends VertexBufferWriter { + ByteBuffer sodium$getBuffer(); + int sodium$getElementOffset(); + void sodium$moveToNextVertex(); + VertexFormatDescription sodium$getFormatDescription(); + boolean sodium$usingFixedColor(); + SodiumBufferBuilder sodium$getDelegate(); +} diff --git a/src/main/java/me/jellysquid/mods/sodium/client/render/vertex/buffer/SodiumBufferBuilder.java b/src/main/java/me/jellysquid/mods/sodium/client/render/vertex/buffer/SodiumBufferBuilder.java new file mode 100644 index 0000000000..b67e882e26 --- /dev/null +++ b/src/main/java/me/jellysquid/mods/sodium/client/render/vertex/buffer/SodiumBufferBuilder.java @@ -0,0 +1,334 @@ +package me.jellysquid.mods.sodium.client.render.vertex.buffer; + +import net.caffeinemc.mods.sodium.api.util.ColorABGR; +import net.caffeinemc.mods.sodium.api.util.ColorARGB; +import net.caffeinemc.mods.sodium.api.util.NormI8; +import net.caffeinemc.mods.sodium.api.vertex.attributes.CommonVertexAttribute; +import net.caffeinemc.mods.sodium.api.vertex.attributes.common.*; +import net.caffeinemc.mods.sodium.api.vertex.buffer.VertexBufferWriter; +import net.caffeinemc.mods.sodium.api.vertex.format.VertexFormatDescription; +import net.minecraft.client.render.BufferBuilder; +import net.minecraft.client.render.VertexConsumer; +import org.lwjgl.system.MemoryStack; +import org.lwjgl.system.MemoryUtil; +import org.spongepowered.asm.mixin.Unique; + +public class SodiumBufferBuilder implements VertexConsumer, VertexBufferWriter { + private static final int ATTRIBUTE_NOT_PRESENT = -1; + + private static final int + ATTRIBUTE_POSITION_BIT = 1 << CommonVertexAttribute.POSITION.ordinal(), + ATTRIBUTE_COLOR_BIT = 1 << CommonVertexAttribute.COLOR.ordinal(), + ATTRIBUTE_TEXTURE_BIT = 1 << CommonVertexAttribute.TEXTURE.ordinal(), + ATTRIBUTE_OVERLAY_BIT = 1 << CommonVertexAttribute.OVERLAY.ordinal(), + ATTRIBUTE_LIGHT_BIT = 1 << CommonVertexAttribute.LIGHT.ordinal(), + ATTRIBUTE_NORMAL_BIT = 1 << CommonVertexAttribute.NORMAL.ordinal(); + + private final ExtendedBufferBuilder builder; + + private int + attributeOffsetPosition, + attributeOffsetColor, + attributeOffsetTexture, + attributeOffsetOverlay, + attributeOffsetLight, + attributeOffsetNormal; + + private int requiredAttributes, writtenAttributes; + + private int packedFixedColor; + + public SodiumBufferBuilder(ExtendedBufferBuilder builder) { + this.builder = builder; + this.resetAttributeBindings(); + this.updateAttributeBindings(this.builder.sodium$getFormatDescription()); + } + + private void resetAttributeBindings() { + this.requiredAttributes = 0; + + this.attributeOffsetPosition = ATTRIBUTE_NOT_PRESENT; + this.attributeOffsetColor = ATTRIBUTE_NOT_PRESENT; + this.attributeOffsetTexture = ATTRIBUTE_NOT_PRESENT; + this.attributeOffsetOverlay = ATTRIBUTE_NOT_PRESENT; + this.attributeOffsetLight = ATTRIBUTE_NOT_PRESENT; + this.attributeOffsetNormal = ATTRIBUTE_NOT_PRESENT; + } + + private void updateAttributeBindings(VertexFormatDescription desc) { + this.resetAttributeBindings(); + + if (desc.containsElement(CommonVertexAttribute.POSITION)) { + this.requiredAttributes |= ATTRIBUTE_POSITION_BIT; + this.attributeOffsetPosition = desc.getElementOffset(CommonVertexAttribute.POSITION); + } + + if (desc.containsElement(CommonVertexAttribute.COLOR)) { + this.requiredAttributes |= ATTRIBUTE_COLOR_BIT; + this.attributeOffsetColor = desc.getElementOffset(CommonVertexAttribute.COLOR); + } + + if (desc.containsElement(CommonVertexAttribute.TEXTURE)) { + this.requiredAttributes |= ATTRIBUTE_TEXTURE_BIT; + this.attributeOffsetTexture = desc.getElementOffset(CommonVertexAttribute.TEXTURE); + } + + if (desc.containsElement(CommonVertexAttribute.OVERLAY)) { + this.requiredAttributes |= ATTRIBUTE_OVERLAY_BIT; + this.attributeOffsetOverlay = desc.getElementOffset(CommonVertexAttribute.OVERLAY); + } + + if (desc.containsElement(CommonVertexAttribute.LIGHT)) { + this.requiredAttributes |= ATTRIBUTE_LIGHT_BIT; + this.attributeOffsetLight = desc.getElementOffset(CommonVertexAttribute.LIGHT); + } + + if (desc.containsElement(CommonVertexAttribute.NORMAL)) { + this.requiredAttributes |= ATTRIBUTE_NORMAL_BIT; + this.attributeOffsetNormal = desc.getElementOffset(CommonVertexAttribute.NORMAL); + } + } + + @Override + public void push(MemoryStack stack, long ptr, int count, VertexFormatDescription format) { + this.builder.push(stack, ptr, count, format); + } + + @Override + public boolean canUseIntrinsics() { + return this.builder.canUseIntrinsics(); + } + + @Unique + private void putPositionAttribute(float x, float y, float z) { + if (this.attributeOffsetPosition == ATTRIBUTE_NOT_PRESENT) { + return; + } + + final long offset = MemoryUtil.memAddress(this.builder.sodium$getBuffer(), this.builder.sodium$getElementOffset() + this.attributeOffsetPosition); + PositionAttribute.put(offset, x, y, z); + + this.writtenAttributes |= ATTRIBUTE_POSITION_BIT; + } + + + @Unique + private void putColorAttribute(int rgba) { + if (this.attributeOffsetColor == ATTRIBUTE_NOT_PRESENT) { + return; + } + + final long offset = MemoryUtil.memAddress(this.builder.sodium$getBuffer(), this.builder.sodium$getElementOffset() + this.attributeOffsetColor); + ColorAttribute.set(offset, rgba); + + this.writtenAttributes |= ATTRIBUTE_COLOR_BIT; + } + + @Unique + private void putTextureAttribute(float u, float v) { + if (this.attributeOffsetTexture == ATTRIBUTE_NOT_PRESENT) { + return; + } + + final long offset = MemoryUtil.memAddress(this.builder.sodium$getBuffer(), this.builder.sodium$getElementOffset() + this.attributeOffsetTexture); + TextureAttribute.put(offset, u, v); + + this.writtenAttributes |= ATTRIBUTE_TEXTURE_BIT; + } + + @Unique + private void putOverlayAttribute(int uv) { + if (this.attributeOffsetOverlay == ATTRIBUTE_NOT_PRESENT) { + return; + } + + final long offset = MemoryUtil.memAddress(this.builder.sodium$getBuffer(), this.builder.sodium$getElementOffset() + this.attributeOffsetOverlay); + OverlayAttribute.set(offset, uv); + + this.writtenAttributes |= ATTRIBUTE_OVERLAY_BIT; + } + + @Unique + private void putLightAttribute(int uv) { + if (this.attributeOffsetLight == ATTRIBUTE_NOT_PRESENT) { + return; + } + + final long offset = MemoryUtil.memAddress(this.builder.sodium$getBuffer(), this.builder.sodium$getElementOffset() + this.attributeOffsetLight); + LightAttribute.set(offset, uv); + + this.writtenAttributes |= ATTRIBUTE_LIGHT_BIT; + } + + @Unique + private void putNormalAttribute(int normal) { + if (this.attributeOffsetNormal == ATTRIBUTE_NOT_PRESENT) { + return; + } + + final long offset = MemoryUtil.memAddress(this.builder.sodium$getBuffer(), this.builder.sodium$getElementOffset() + this.attributeOffsetNormal); + NormalAttribute.set(offset, normal); + + this.writtenAttributes |= ATTRIBUTE_NORMAL_BIT; + } + + @Override + public void vertex(float x, float y, float z, + float red, float green, float blue, float alpha, + float u, float v, + int overlay, int light, + float normalX, float normalY, float normalZ + ) { + if (this.builder.sodium$usingFixedColor()) { + throw new IllegalStateException(); + } + + final long offset = MemoryUtil.memAddress(this.builder.sodium$getBuffer(), this.builder.sodium$getElementOffset()); + + if (this.attributeOffsetPosition != ATTRIBUTE_NOT_PRESENT) { + PositionAttribute.put(offset + this.attributeOffsetPosition, x, y, z); + } + + if (this.attributeOffsetColor != ATTRIBUTE_NOT_PRESENT) { + ColorAttribute.set(offset + this.attributeOffsetColor, ColorABGR.pack(red, green, blue, alpha)); + } + + if (this.attributeOffsetTexture != ATTRIBUTE_NOT_PRESENT) { + TextureAttribute.put(offset + this.attributeOffsetTexture, u, v); + } + + if (this.attributeOffsetOverlay != ATTRIBUTE_NOT_PRESENT) { + OverlayAttribute.set(offset + this.attributeOffsetOverlay, overlay); + } + + if (this.attributeOffsetLight != ATTRIBUTE_NOT_PRESENT) { + LightAttribute.set(offset + this.attributeOffsetLight, light); + } + + if (this.attributeOffsetNormal != ATTRIBUTE_NOT_PRESENT) { + NormalAttribute.set(offset + this.attributeOffsetNormal, NormI8.pack(normalX, normalY, normalZ)); + } + + // It's okay to mark elements as "written to" even if the vertex format does not specify those elements. + this.writtenAttributes = ATTRIBUTE_POSITION_BIT | ATTRIBUTE_COLOR_BIT | ATTRIBUTE_TEXTURE_BIT | + ATTRIBUTE_OVERLAY_BIT | ATTRIBUTE_LIGHT_BIT | ATTRIBUTE_NORMAL_BIT; + + this.next(); + } + + @Override + public void fixedColor(int red, int green, int blue, int alpha) { + ((BufferBuilder)this.builder).fixedColor(red, green, blue, alpha); + this.packedFixedColor = ColorABGR.pack(red, green, blue, alpha); + } + + @Override + public void unfixColor() { + ((BufferBuilder)this.builder).unfixColor(); + } + + @Override + public VertexConsumer vertex(double x, double y, double z) { + this.putPositionAttribute((float) x, (float) y, (float) z); + + return this; + } + + @Override + public VertexConsumer color(int red, int green, int blue, int alpha) { + if (this.builder.sodium$usingFixedColor()) { + throw new IllegalStateException(); + } + + this.putColorAttribute(ColorABGR.pack(red, green, blue, alpha)); + + return this; + } + + @Override + public VertexConsumer color(int argb) { // No, this isn't a typo. One method takes RGBA, but this one takes ARGB. + if (this.builder.sodium$usingFixedColor()) { + throw new IllegalStateException(); + } + + // This should be RGBA. + // There is no reason it should be anything other than RGBA. + // It should certainly never be ABGR. + // But it is. + // Why? + this.putColorAttribute(ColorARGB.toABGR(argb)); + + return this; + } + + @Override + public VertexConsumer texture(float u, float v) { + this.putTextureAttribute(u, v); + + return this; + } + + @Override + public VertexConsumer overlay(int uv) { + this.putOverlayAttribute(uv); + + return this; + } + + + @Override + public VertexConsumer light(int uv) { + this.putLightAttribute(uv); + + return this; + } + @Override + public VertexConsumer normal(float x, float y, float z) { + this.putNormalAttribute(NormI8.pack(x, y, z)); + + return this; + } + + @Override + public void next() { + if (this.builder.sodium$usingFixedColor()) { + this.putColorAttribute(this.packedFixedColor); + } + + if (!this.isVertexFinished()) { + throw new IllegalStateException("Not filled all elements of the vertex"); + } + + this.builder.sodium$moveToNextVertex(); + + this.writtenAttributes = 0; + } + + public void reset() { + this.writtenAttributes = 0; + } + + public BufferBuilder getOriginalBufferBuilder() { + return (BufferBuilder)this.builder; + } + + private boolean isVertexFinished() { + return (this.writtenAttributes & this.requiredAttributes) == this.requiredAttributes; + } + + @Override + public VertexConsumer light(int u, int v) { + return this.light(packU16x2(u, v)); + } + + @Override + public VertexConsumer overlay(int u, int v) { + return this.overlay(packU16x2(u, v)); + } + + @Unique + private static int packU16x2(int u, int v) { + return (u & 0xFFFF) << 0 | + (v & 0xFFFF) << 16; + } +} diff --git a/src/main/java/me/jellysquid/mods/sodium/mixin/core/render/immediate/consumer/BufferBuilderMixin.java b/src/main/java/me/jellysquid/mods/sodium/mixin/core/render/immediate/consumer/BufferBuilderMixin.java index 869a330b67..579273d22c 100644 --- a/src/main/java/me/jellysquid/mods/sodium/mixin/core/render/immediate/consumer/BufferBuilderMixin.java +++ b/src/main/java/me/jellysquid/mods/sodium/mixin/core/render/immediate/consumer/BufferBuilderMixin.java @@ -1,5 +1,7 @@ package me.jellysquid.mods.sodium.mixin.core.render.immediate.consumer; +import me.jellysquid.mods.sodium.client.render.vertex.buffer.ExtendedBufferBuilder; +import me.jellysquid.mods.sodium.client.render.vertex.buffer.SodiumBufferBuilder; import net.caffeinemc.mods.sodium.api.memory.MemoryIntrinsics; import net.caffeinemc.mods.sodium.api.util.ColorABGR; import net.caffeinemc.mods.sodium.api.util.ColorARGB; @@ -25,22 +27,10 @@ import java.nio.ByteBuffer; @Mixin(BufferBuilder.class) -public abstract class BufferBuilderMixin extends FixedColorVertexConsumer implements VertexBufferWriter { +public abstract class BufferBuilderMixin extends FixedColorVertexConsumer implements VertexBufferWriter, ExtendedBufferBuilder { @Shadow protected abstract void grow(int size); - @Unique - private static final int ATTRIBUTE_NOT_PRESENT = -1; - - @Unique - private static final int - ATTRIBUTE_POSITION_BIT = 1 << CommonVertexAttribute.POSITION.ordinal(), - ATTRIBUTE_COLOR_BIT = 1 << CommonVertexAttribute.COLOR.ordinal(), - ATTRIBUTE_TEXTURE_BIT = 1 << CommonVertexAttribute.TEXTURE.ordinal(), - ATTRIBUTE_OVERLAY_BIT = 1 << CommonVertexAttribute.OVERLAY.ordinal(), - ATTRIBUTE_LIGHT_BIT = 1 << CommonVertexAttribute.LIGHT.ordinal(), - ATTRIBUTE_NORMAL_BIT = 1 << CommonVertexAttribute.NORMAL.ordinal(); - @Shadow private ByteBuffer buffer; @@ -59,34 +49,7 @@ public abstract class BufferBuilderMixin extends FixedColorVertexConsumer implem @Unique private int vertexStride; - @Unique - private int - attributeOffsetPosition, - attributeOffsetColor, - attributeOffsetTexture, - attributeOffsetOverlay, - attributeOffsetLight, - attributeOffsetNormal; - - @Unique - private int requiredAttributes, writtenAttributes; - - @Inject(method = "", at = @At("RETURN")) - private void onInit(int initialCapacity, CallbackInfo ci) { - this.resetAttributeBindings(); - } - - @Unique - private void resetAttributeBindings() { - this.requiredAttributes = 0; - - this.attributeOffsetPosition = ATTRIBUTE_NOT_PRESENT; - this.attributeOffsetColor = ATTRIBUTE_NOT_PRESENT; - this.attributeOffsetTexture = ATTRIBUTE_NOT_PRESENT; - this.attributeOffsetOverlay = ATTRIBUTE_NOT_PRESENT; - this.attributeOffsetLight = ATTRIBUTE_NOT_PRESENT; - this.attributeOffsetNormal = ATTRIBUTE_NOT_PRESENT; - } + private SodiumBufferBuilder fastDelegate; @Inject( method = "setFormat", @@ -100,326 +63,41 @@ private void onFormatChanged(VertexFormat format, CallbackInfo ci) { this.formatDescription = VertexFormatRegistry.instance() .get(format); this.vertexStride = this.formatDescription.stride(); - - this.updateAttributeBindings(this.formatDescription); - } - - @Unique - private void updateAttributeBindings(VertexFormatDescription desc) { - this.resetAttributeBindings(); - - if (desc.containsElement(CommonVertexAttribute.POSITION)) { - this.requiredAttributes |= ATTRIBUTE_POSITION_BIT; - this.attributeOffsetPosition = desc.getElementOffset(CommonVertexAttribute.POSITION); - } - - if (desc.containsElement(CommonVertexAttribute.COLOR)) { - this.requiredAttributes |= ATTRIBUTE_COLOR_BIT; - this.attributeOffsetColor = desc.getElementOffset(CommonVertexAttribute.COLOR); - } - - if (desc.containsElement(CommonVertexAttribute.TEXTURE)) { - this.requiredAttributes |= ATTRIBUTE_TEXTURE_BIT; - this.attributeOffsetTexture = desc.getElementOffset(CommonVertexAttribute.TEXTURE); - } - - if (desc.containsElement(CommonVertexAttribute.OVERLAY)) { - this.requiredAttributes |= ATTRIBUTE_OVERLAY_BIT; - this.attributeOffsetOverlay = desc.getElementOffset(CommonVertexAttribute.OVERLAY); - } - - if (desc.containsElement(CommonVertexAttribute.LIGHT)) { - this.requiredAttributes |= ATTRIBUTE_LIGHT_BIT; - this.attributeOffsetLight = desc.getElementOffset(CommonVertexAttribute.LIGHT); - } - - if (desc.containsElement(CommonVertexAttribute.NORMAL)) { - this.requiredAttributes |= ATTRIBUTE_NORMAL_BIT; - this.attributeOffsetNormal = desc.getElementOffset(CommonVertexAttribute.NORMAL); - } - } - - @Inject( - method = "begin", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/client/render/BufferBuilder;setFormat(Lnet/minecraft/client/render/VertexFormat;)V" - ) - ) - private void onBegin(VertexFormat.DrawMode drawMode, VertexFormat format, CallbackInfo ci) { - this.writtenAttributes = 0; - } - - @Inject(method = "resetBuilding", at = @At("RETURN")) - private void onResetBuilding(CallbackInfo ci) { - this.writtenAttributes = 0; - } - - @Inject(method = "reset", at = @At("RETURN")) - private void onReset(CallbackInfo ci) { - this.writtenAttributes = 0; - } - - @Unique - private void putPositionAttribute(float x, float y, float z) { - if (this.attributeOffsetPosition == ATTRIBUTE_NOT_PRESENT) { - return; - } - - final long offset = MemoryUtil.memAddress(this.buffer, this.elementOffset + this.attributeOffsetPosition); - PositionAttribute.put(offset, x, y, z); - - this.writtenAttributes |= ATTRIBUTE_POSITION_BIT; - } - - - @Unique - private void putColorAttribute(int rgba) { - if (this.attributeOffsetColor == ATTRIBUTE_NOT_PRESENT) { - return; - } - - final long offset = MemoryUtil.memAddress(this.buffer, this.elementOffset + this.attributeOffsetColor); - ColorAttribute.set(offset, rgba); - - this.writtenAttributes |= ATTRIBUTE_COLOR_BIT; - } - - @Unique - private void putTextureAttribute(float u, float v) { - if (this.attributeOffsetTexture == ATTRIBUTE_NOT_PRESENT) { - return; - } - - final long offset = MemoryUtil.memAddress(this.buffer, this.elementOffset + this.attributeOffsetTexture); - TextureAttribute.put(offset, u, v); - - this.writtenAttributes |= ATTRIBUTE_TEXTURE_BIT; - } - - @Unique - private void putOverlayAttribute(int uv) { - if (this.attributeOffsetOverlay == ATTRIBUTE_NOT_PRESENT) { - return; - } - - final long offset = MemoryUtil.memAddress(this.buffer, this.elementOffset + this.attributeOffsetOverlay); - OverlayAttribute.set(offset, uv); - - this.writtenAttributes |= ATTRIBUTE_OVERLAY_BIT; - } - - @Unique - private void putLightAttribute(int uv) { - if (this.attributeOffsetLight == ATTRIBUTE_NOT_PRESENT) { - return; - } - - final long offset = MemoryUtil.memAddress(this.buffer, this.elementOffset + this.attributeOffsetLight); - LightAttribute.set(offset, uv); - - this.writtenAttributes |= ATTRIBUTE_LIGHT_BIT; - } - - @Unique - private void putNormalAttribute(int normal) { - if (this.attributeOffsetNormal == ATTRIBUTE_NOT_PRESENT) { - return; - } - - final long offset = MemoryUtil.memAddress(this.buffer, this.elementOffset + this.attributeOffsetNormal); - NormalAttribute.set(offset, normal); - - this.writtenAttributes |= ATTRIBUTE_NORMAL_BIT; - } - - @Override - public void vertex(float x, float y, float z, - float red, float green, float blue, float alpha, - float u, float v, - int overlay, int light, - float normalX, float normalY, float normalZ - ) { - if (this.colorFixed) { - throw new IllegalStateException(); - } - - final long offset = MemoryUtil.memAddress(this.buffer, this.elementOffset); - - if (this.attributeOffsetPosition != ATTRIBUTE_NOT_PRESENT) { - PositionAttribute.put(offset + this.attributeOffsetPosition, x, y, z); - } - - if (this.attributeOffsetColor != ATTRIBUTE_NOT_PRESENT) { - ColorAttribute.set(offset + this.attributeOffsetColor, ColorABGR.pack(red, green, blue, alpha)); - } - - if (this.attributeOffsetTexture != ATTRIBUTE_NOT_PRESENT) { - TextureAttribute.put(offset + this.attributeOffsetTexture, u, v); - } - - if (this.attributeOffsetOverlay != ATTRIBUTE_NOT_PRESENT) { - OverlayAttribute.set(offset + this.attributeOffsetOverlay, overlay); - } - - if (this.attributeOffsetLight != ATTRIBUTE_NOT_PRESENT) { - LightAttribute.set(offset + this.attributeOffsetLight, light); - } - - if (this.attributeOffsetNormal != ATTRIBUTE_NOT_PRESENT) { - NormalAttribute.set(offset + this.attributeOffsetNormal, NormI8.pack(normalX, normalY, normalZ)); - } - - // It's okay to mark elements as "written to" even if the vertex format does not specify those elements. - this.writtenAttributes = ATTRIBUTE_POSITION_BIT | ATTRIBUTE_COLOR_BIT | ATTRIBUTE_TEXTURE_BIT | - ATTRIBUTE_OVERLAY_BIT | ATTRIBUTE_LIGHT_BIT | ATTRIBUTE_NORMAL_BIT; - - this.next(); - } - - @Override - public VertexConsumer vertex(double x, double y, double z) { - this.putPositionAttribute((float) x, (float) y, (float) z); - - return this; + this.fastDelegate = this.formatDescription.isSimpleFormat() ? new SodiumBufferBuilder(this) : null; } - @Override - public VertexConsumer color(int red, int green, int blue, int alpha) { - if (this.colorFixed) { - throw new IllegalStateException(); + @Inject(method = { "reset", "resetBuilding", "begin" }, at = @At("RETURN")) + private void resetDelegate(CallbackInfo ci) { + if (this.fastDelegate != null) { + this.fastDelegate.reset(); } - - this.putColorAttribute(ColorABGR.pack(red, green, blue, alpha)); - - return this; - } - - @Override - public VertexConsumer color(int argb) { // No, this isn't a typo. One method takes RGBA, but this one takes ARGB. - if (this.colorFixed) { - throw new IllegalStateException(); - } - - // This should be RGBA. - // There is no reason it should be anything other than RGBA. - // It should certainly never be ABGR. - // But it is. - // Why? - this.putColorAttribute(ColorARGB.toABGR(argb)); - - return this; } @Override - public VertexConsumer texture(float u, float v) { - this.putTextureAttribute(u, v); - - return this; - } - - @Override - public VertexConsumer overlay(int uv) { - this.putOverlayAttribute(uv); - - return this; + public ByteBuffer sodium$getBuffer() { + return this.buffer; } - - @Override - public VertexConsumer light(int uv) { - this.putLightAttribute(uv); - - return this; - } @Override - public VertexConsumer normal(float x, float y, float z) { - this.putNormalAttribute(NormI8.pack(x, y, z)); - - return this; + public int sodium$getElementOffset() { + return this.elementOffset; } @Override - public VertexConsumer light(int u, int v) { - return this.light(packU16x2(u, v)); + public VertexFormatDescription sodium$getFormatDescription() { + return this.formatDescription; } @Override - public VertexConsumer overlay(int u, int v) { - return this.overlay(packU16x2(u, v)); - } - - @Unique - private static int packU16x2(int u, int v) { - return (u & 0xFFFF) << 0 | - (v & 0xFFFF) << 16; - } - - /** - * @author JellySquid - * @reason Only used by BufferVertexConsumer's default implementations, which our patches remove - */ - @Overwrite - public VertexFormatElement getCurrentElement() { - throw createBlockedUpcallException(); - } - - /** - * @author JellySquid - * @reason Only used by BufferVertexConsumer's default implementations, which our patches remove - */ - @Overwrite - public void nextElement() { - throw createBlockedUpcallException(); - } - - /** - * @author JellySquid - * @reason Only used by BufferVertexConsumer's default implementations, which our patches remove - */ - @Overwrite - public void putByte(int index, byte value) { - throw createBlockedUpcallException(); - } - - /** - * @author JellySquid - * @reason Only used by BufferVertexConsumer's default implementations, which our patches remove - */ - @Overwrite - public void putShort(int index, short value) { - throw createBlockedUpcallException(); - } - - /** - * @author JellySquid - * @reason Only used by BufferVertexConsumer's default implementations, which our patches remove - */ - @Overwrite - public void putFloat(int index, float value) { - throw createBlockedUpcallException(); + public SodiumBufferBuilder sodium$getDelegate() { + return this.fastDelegate; } - /** - * @author JellySquid - * @reason The implementation no longer cares about the current element - */ - @Overwrite @Override - public void next() { - if (this.colorFixed) { - this.writeFixedColor(); - } - - if (!this.isVertexFinished()) { - throw new IllegalStateException("Not filled all elements of the vertex"); - } - + public void sodium$moveToNextVertex() { this.vertexCount++; this.elementOffset += this.vertexStride; - this.writtenAttributes = 0; - this.grow(this.vertexStride); if (this.shouldDuplicateVertices()) { @@ -427,14 +105,9 @@ public void next() { } } - @Unique - private boolean isVertexFinished() { - return (this.writtenAttributes & this.requiredAttributes) == this.requiredAttributes; - } - - @Unique - private void writeFixedColor() { - this.putColorAttribute(ColorABGR.pack(this.fixedRed, this.fixedGreen, this.fixedBlue, this.fixedAlpha)); + @Override + public boolean sodium$usingFixedColor() { + return this.colorFixed; } @Unique @@ -457,7 +130,7 @@ private void duplicateVertex() { @Override public boolean canUseIntrinsics() { - return true; + return this.formatDescription != null && this.formatDescription.isSimpleFormat(); } @Override @@ -490,9 +163,4 @@ private void copySlow(long src, long dst, int count, VertexFormatDescription for .get(format, this.formatDescription) .serialize(src, dst, count); } - - @Unique - private static RuntimeException createBlockedUpcallException() { - return new UnsupportedOperationException("The internal methods provided by BufferVertexConsumer (as used to upcall into BufferBuilder) are unsupported"); - } } diff --git a/src/main/java/me/jellysquid/mods/sodium/mixin/core/render/immediate/consumer/VertexConsumerProviderImmediateMixin.java b/src/main/java/me/jellysquid/mods/sodium/mixin/core/render/immediate/consumer/VertexConsumerProviderImmediateMixin.java new file mode 100644 index 0000000000..ed0ae76c06 --- /dev/null +++ b/src/main/java/me/jellysquid/mods/sodium/mixin/core/render/immediate/consumer/VertexConsumerProviderImmediateMixin.java @@ -0,0 +1,34 @@ +package me.jellysquid.mods.sodium.mixin.core.render.immediate.consumer; + +import me.jellysquid.mods.sodium.client.render.vertex.buffer.ExtendedBufferBuilder; +import me.jellysquid.mods.sodium.client.render.vertex.buffer.SodiumBufferBuilder; +import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.VertexConsumerProvider; +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.ModifyVariable; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(VertexConsumerProvider.Immediate.class) +public class VertexConsumerProviderImmediateMixin { + @Inject(method = "getBuffer", at = @At("RETURN"), cancellable = true) + private void useFasterVertexConsumer(RenderLayer layer, CallbackInfoReturnable cir) { + if (cir.getReturnValue() instanceof ExtendedBufferBuilder bufferBuilder) { + SodiumBufferBuilder replacement = bufferBuilder.sodium$getDelegate(); + if (replacement != null) { + cir.setReturnValue(replacement); + } + } + } + + @ModifyVariable(method = "method_24213", at = @At(value = "LOAD", ordinal = 0)) + private VertexConsumer changeComparedVertexConsumer(VertexConsumer input) { + if (input instanceof SodiumBufferBuilder replacement) { + return replacement.getOriginalBufferBuilder(); + } else { + return input; + } + } +} diff --git a/src/main/resources/sodium.mixins.json b/src/main/resources/sodium.mixins.json index 2c68174c75..8f0769414c 100644 --- a/src/main/resources/sodium.mixins.json +++ b/src/main/resources/sodium.mixins.json @@ -22,6 +22,7 @@ "core.render.immediate.consumer.OutlineVertexConsumerMixin", "core.render.immediate.consumer.OverlayVertexConsumerMixin", "core.render.immediate.consumer.SpriteTexturedVertexConsumerMixin", + "core.render.immediate.consumer.VertexConsumerProviderImmediateMixin", "core.render.immediate.consumer.VertexConsumersMixin$DualMixin", "core.render.immediate.consumer.VertexConsumersMixin$UnionMixin", "core.render.world.BufferBuilderStorageMixin",