diff --git a/projects/common/src/client/java/dan200/computercraft/client/integration/IrisShaderMod.java b/projects/common/src/client/java/dan200/computercraft/client/integration/IrisShaderMod.java index 85581bb84..1a6b33bae 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/integration/IrisShaderMod.java +++ b/projects/common/src/client/java/dan200/computercraft/client/integration/IrisShaderMod.java @@ -5,18 +5,16 @@ package dan200.computercraft.client.integration; import com.google.auto.service.AutoService; -import com.mojang.blaze3d.vertex.ByteBufferBuilder; import com.mojang.blaze3d.vertex.VertexFormat; import dan200.computercraft.client.render.text.DirectFixedWidthFontRenderer; import dan200.computercraft.shared.platform.PlatformHelper; import net.irisshaders.iris.api.v0.IrisApi; import net.irisshaders.iris.api.v0.IrisTextVertexSink; import net.minecraft.client.renderer.LightTexture; -import org.jspecify.annotations.Nullable; -import org.lwjgl.system.MemoryUtil; import java.nio.ByteBuffer; import java.util.Optional; +import java.util.function.IntFunction; @AutoService(ShaderMod.Provider.class) public class IrisShaderMod implements ShaderMod.Provider { @@ -32,21 +30,20 @@ public class IrisShaderMod implements ShaderMod.Provider { } @Override - public DirectFixedWidthFontRenderer.QuadEmitter getQuadEmitter(int vertexCount, ByteBufferBuilder makeBuffer) { - return IrisApi.getInstance().getMinorApiRevision() >= 1 - ? new IrisQuadEmitter(vertexCount, makeBuffer) - : super.getQuadEmitter(vertexCount, makeBuffer); + public DirectFixedWidthFontRenderer.QuadEmitter getQuadEmitter(int quadCount, IntFunction makeBuffer) { + return new IrisQuadEmitter(quadCount, makeBuffer); } private static final class IrisQuadEmitter extends DirectFixedWidthFontRenderer.QuadEmitter { private final IrisTextVertexSink sink; - private @Nullable ByteBuffer buffer; - private IrisQuadEmitter(int vertexCount, ByteBufferBuilder builder) { - sink = IrisApi.getInstance().createTextVertexSink(vertexCount, i -> { - if (buffer != null) throw new IllegalStateException("Allocated multiple buffers"); - return buffer = MemoryUtil.memByteBuffer(builder.reserve(i), i); - }); + private IrisQuadEmitter(int vertexCount, IntFunction builder) { + sink = IrisApi.getInstance().createTextVertexSink(vertexCount, builder); + } + + @Override + public ByteBuffer byteBuffer() { + return sink.getUnderlyingByteBuffer(); } @Override diff --git a/projects/common/src/client/java/dan200/computercraft/client/integration/ShaderMod.java b/projects/common/src/client/java/dan200/computercraft/client/integration/ShaderMod.java index 6285229cc..b49f02464 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/integration/ShaderMod.java +++ b/projects/common/src/client/java/dan200/computercraft/client/integration/ShaderMod.java @@ -4,11 +4,14 @@ package dan200.computercraft.client.integration; -import com.mojang.blaze3d.vertex.ByteBufferBuilder; import dan200.computercraft.client.render.text.DirectFixedWidthFontRenderer; +import java.nio.ByteBuffer; import java.util.Optional; import java.util.ServiceLoader; +import java.util.function.IntFunction; + +import static dan200.computercraft.client.render.text.FixedWidthFontRenderer.TERMINAL_TEXT; /** * Find the currently loaded shader mod (if present) and provides utilities for interacting with it. @@ -30,12 +33,12 @@ public class ShaderMod { /** * Get an appropriate quad emitter for use with a vertex buffer and {@link DirectFixedWidthFontRenderer} . * - * @param vertexCount The number of vertices. - * @param buffer A function to allocate a temporary buffer. + * @param quadCount The number of quads. + * @param makeBuffer A function to allocate a temporary buffer. * @return The quad emitter. */ - public DirectFixedWidthFontRenderer.QuadEmitter getQuadEmitter(int vertexCount, ByteBufferBuilder buffer) { - return new DirectFixedWidthFontRenderer.ByteBufferEmitter(buffer); + public DirectFixedWidthFontRenderer.QuadEmitter getQuadEmitter(int quadCount, IntFunction makeBuffer) { + return new DirectFixedWidthFontRenderer.ByteBufferEmitter(makeBuffer.apply(TERMINAL_TEXT.format().getVertexSize() * quadCount * 4)); } public interface Provider { diff --git a/projects/common/src/client/java/dan200/computercraft/client/render/monitor/MonitorBlockEntityRenderer.java b/projects/common/src/client/java/dan200/computercraft/client/render/monitor/MonitorBlockEntityRenderer.java index 1d3bbef15..a6ea0649b 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/render/monitor/MonitorBlockEntityRenderer.java +++ b/projects/common/src/client/java/dan200/computercraft/client/render/monitor/MonitorBlockEntityRenderer.java @@ -7,7 +7,6 @@ package dan200.computercraft.client.render.monitor; import com.mojang.blaze3d.buffers.BufferType; import com.mojang.blaze3d.buffers.BufferUsage; import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.ByteBufferBuilder; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; import dan200.computercraft.annotations.ForgeOverride; @@ -28,7 +27,10 @@ import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import org.joml.Matrix4f; +import org.jspecify.annotations.Nullable; +import org.lwjgl.system.MemoryUtil; +import java.nio.ByteBuffer; import java.util.OptionalDouble; import java.util.OptionalInt; @@ -42,7 +44,7 @@ public class MonitorBlockEntityRenderer implements BlockEntityRenderer renderState.vertexBuffer.size()) { - if (renderState.vertexBuffer != null) { - renderState.vertexBuffer.close(); - renderState.vertexBuffer = null; - } - renderState.vertexBuffer = RenderSystem.getDevice().createBuffer( - () -> "Monitor at " + monitor.getOrigin().getBlockPos(), - BufferType.VERTICES, BufferUsage.STATIC_WRITE, resultBuffer - ); - } else if (!renderState.vertexBuffer.isClosed()) { - commandEncoder.writeToBuffer(renderState.vertexBuffer, resultBuffer, 0); - } + // Ensure our buffer contains the correct number of vertices. + if (resultBuffer.remaining() != sink.format().getVertexSize() * vertexCountAfterCursor) { + throw new IllegalStateException(String.format( + "Mismatched vertex count. Buffer is %d bytes long, but was expected to be %d (vertex size) * %d (vertex count) = %d bytes.", + resultBuffer.limit(), sink.format().getVertexSize(), vertexCountAfterCursor, sink.format().getVertexSize() * vertexCountAfterCursor + )); } + + // Upload the buffer, reallocating if required. + if (renderState.vertexBuffer == null || resultBuffer.remaining() > renderState.vertexBuffer.size()) { + if (renderState.vertexBuffer != null) { + renderState.vertexBuffer.close(); + renderState.vertexBuffer = null; + } + renderState.vertexBuffer = RenderSystem.getDevice().createBuffer( + () -> "Monitor at " + monitor.getOrigin().getBlockPos(), + BufferType.VERTICES, BufferUsage.STATIC_WRITE, resultBuffer + ); + } else if (!renderState.vertexBuffer.isClosed()) { + commandEncoder.writeToBuffer(renderState.vertexBuffer, resultBuffer, 0); + } + + var mode = FixedWidthFontRenderer.TERMINAL_TEXT.mode(); + indexAfterBackground = mode.indexCount(vertexCountAfterBackground); + indexAfterForeground = mode.indexCount(vertexCountAfterForeground); + indexAfterCursor = mode.indexCount(vertexCountAfterCursor); } - var mode = FixedWidthFontRenderer.TERMINAL_TEXT.mode(); - renderState.indexAfterBackground = mode.indexCount(vertexCountAfterBackground); - renderState.indexAfterForeground = mode.indexCount(vertexCountAfterForeground); - renderState.indexAfterCursor = mode.indexCount(vertexCountAfterCursor); + renderState.indexAfterForeground = indexAfterForeground; + renderState.indexAfterBackground = indexAfterBackground; + renderState.indexAfterCursor = indexAfterCursor; } if (renderState.indexAfterCursor == 0) return; @@ -249,4 +260,14 @@ public class MonitorBlockEntityRenderer implements BlockEntityRenderer