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 66d7a3d338..9b8aa661c2 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,9 +28,4 @@ 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 1fa17d9db7..eb93054a34 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,10 +4,8 @@ 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 { @@ -16,29 +14,11 @@ 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) { @@ -86,9 +66,4 @@ 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 deleted file mode 100644 index 5caf3d12ef..0000000000 --- a/src/main/java/me/jellysquid/mods/sodium/client/render/vertex/buffer/ExtendedBufferBuilder.java +++ /dev/null @@ -1,15 +0,0 @@ -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 deleted file mode 100644 index b67e882e26..0000000000 --- a/src/main/java/me/jellysquid/mods/sodium/client/render/vertex/buffer/SodiumBufferBuilder.java +++ /dev/null @@ -1,334 +0,0 @@ -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 579273d22c..869a330b67 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,7 +1,5 @@ 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; @@ -27,10 +25,22 @@ import java.nio.ByteBuffer; @Mixin(BufferBuilder.class) -public abstract class BufferBuilderMixin extends FixedColorVertexConsumer implements VertexBufferWriter, ExtendedBufferBuilder { +public abstract class BufferBuilderMixin extends FixedColorVertexConsumer implements VertexBufferWriter { @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; @@ -49,7 +59,34 @@ public abstract class BufferBuilderMixin extends FixedColorVertexConsumer implem @Unique private int vertexStride; - private SodiumBufferBuilder fastDelegate; + @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; + } @Inject( method = "setFormat", @@ -63,41 +100,326 @@ private void onFormatChanged(VertexFormat format, CallbackInfo ci) { this.formatDescription = VertexFormatRegistry.instance() .get(format); this.vertexStride = this.formatDescription.stride(); - this.fastDelegate = this.formatDescription.isSimpleFormat() ? new SodiumBufferBuilder(this) : null; + + 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; } - @Inject(method = { "reset", "resetBuilding", "begin" }, at = @At("RETURN")) - private void resetDelegate(CallbackInfo ci) { - if (this.fastDelegate != null) { - this.fastDelegate.reset(); + @Override + public VertexConsumer color(int red, int green, int blue, int alpha) { + if (this.colorFixed) { + 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.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 ByteBuffer sodium$getBuffer() { - return this.buffer; + 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 int sodium$getElementOffset() { - return this.elementOffset; + public VertexConsumer normal(float x, float y, float z) { + this.putNormalAttribute(NormI8.pack(x, y, z)); + + return this; } @Override - public VertexFormatDescription sodium$getFormatDescription() { - return this.formatDescription; + public VertexConsumer light(int u, int v) { + return this.light(packU16x2(u, v)); } @Override - public SodiumBufferBuilder sodium$getDelegate() { - return this.fastDelegate; + 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(); } + /** + * @author JellySquid + * @reason The implementation no longer cares about the current element + */ + @Overwrite @Override - public void sodium$moveToNextVertex() { + public void next() { + if (this.colorFixed) { + this.writeFixedColor(); + } + + if (!this.isVertexFinished()) { + throw new IllegalStateException("Not filled all elements of the vertex"); + } + this.vertexCount++; this.elementOffset += this.vertexStride; + this.writtenAttributes = 0; + this.grow(this.vertexStride); if (this.shouldDuplicateVertices()) { @@ -105,9 +427,14 @@ private void resetDelegate(CallbackInfo ci) { } } - @Override - public boolean sodium$usingFixedColor() { - return this.colorFixed; + @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)); } @Unique @@ -130,7 +457,7 @@ private void duplicateVertex() { @Override public boolean canUseIntrinsics() { - return this.formatDescription != null && this.formatDescription.isSimpleFormat(); + return true; } @Override @@ -163,4 +490,9 @@ 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 deleted file mode 100644 index ed0ae76c06..0000000000 --- a/src/main/java/me/jellysquid/mods/sodium/mixin/core/render/immediate/consumer/VertexConsumerProviderImmediateMixin.java +++ /dev/null @@ -1,34 +0,0 @@ -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/fabric.mod.json b/src/main/resources/fabric.mod.json index 06409e9694..1cff6e4cf7 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -33,7 +33,8 @@ "@douira", "@burgerindividual", "@TwistedZero", - "@Leo40Git" + "@Leo40Git", + "@haykam821" ], "contact": { "homepage": "https://github.com/CaffeineMC/sodium-fabric", diff --git a/src/main/resources/sodium.mixins.json b/src/main/resources/sodium.mixins.json index e0c9bf84e5..56e17be734 100644 --- a/src/main/resources/sodium.mixins.json +++ b/src/main/resources/sodium.mixins.json @@ -21,7 +21,6 @@ "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", "features.gui.hooks.console.GameRendererMixin",