From 77a00b14ae541d21afe0104939290a556e48274b Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Tue, 26 Apr 2022 19:14:37 +0100 Subject: [PATCH] Use UBOs for the TBO renderer Like #455, this sets our uniforms via a UBO rather than having separate ones for each value. There are a couple of small differences: - Have a UBO for each monitor, rather than sharing one and rewriting it every monitor. This means we only need to update the buffer when the monitor changes. - Use std140 rather than the default layout. This means we don't have to care about location/stride in the buffer. Also like #455, this doesn't actually seem to result in any performance improvements for me. However, it does make it a bit easier to handle a large number of uniforms. Also cleans up the generation of the main monitor texture buffer: - Move buffer generation into a separate method - just ensures that it shows up separately in profilers. - Explicitly pass the position when setting bytes, rather than incrementing the internal one. This saves some memory reads/writes (I thought Java optimised them out, evidently not!). Saves a few fps when updating. - Use DSA when possible. Unclear if it helps at all, but nice to do :). --- .../render/MonitorTextureBufferShader.java | 87 +++++++++++++------ .../render/TileEntityMonitorRenderer.java | 28 ++---- .../peripheral/monitor/ClientMonitor.java | 16 +++- .../assets/computercraft/shaders/monitor.frag | 9 +- 4 files changed, 87 insertions(+), 53 deletions(-) diff --git a/src/main/java/dan200/computercraft/client/render/MonitorTextureBufferShader.java b/src/main/java/dan200/computercraft/client/render/MonitorTextureBufferShader.java index e387e7cab..cb82369f1 100644 --- a/src/main/java/dan200/computercraft/client/render/MonitorTextureBufferShader.java +++ b/src/main/java/dan200/computercraft/client/render/MonitorTextureBufferShader.java @@ -10,61 +10,49 @@ import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; import dan200.computercraft.ComputerCraft; import dan200.computercraft.client.render.text.FixedWidthFontRenderer; +import dan200.computercraft.core.terminal.Terminal; +import dan200.computercraft.core.terminal.TextBuffer; +import dan200.computercraft.shared.util.Colour; import dan200.computercraft.shared.util.Palette; import net.minecraft.client.renderer.texture.TextureUtil; import net.minecraft.util.math.vector.Matrix4f; import org.lwjgl.BufferUtils; import org.lwjgl.opengl.GL13; import org.lwjgl.opengl.GL20; +import org.lwjgl.opengl.GL31; import java.io.InputStream; +import java.nio.ByteBuffer; import java.nio.FloatBuffer; +import static dan200.computercraft.client.render.text.FixedWidthFontRenderer.getColour; + class MonitorTextureBufferShader { + public static final int UNIFORM_SIZE = 4 * 4 * 16 + 4 + 4; + static final int TEXTURE_INDEX = GL13.GL_TEXTURE3; private static final FloatBuffer MATRIX_BUFFER = BufferUtils.createFloatBuffer( 16 ); - private static final FloatBuffer PALETTE_BUFFER = BufferUtils.createFloatBuffer( 16 * 3 ); private static int uniformMv; private static int uniformFont; - private static int uniformWidth; - private static int uniformHeight; private static int uniformTbo; - private static int uniformPalette; + private static int uniformMonitor; private static boolean initialised; private static boolean ok; private static int program; - static void setupUniform( Matrix4f transform, int width, int height, Palette palette, boolean greyscale ) + static void setupUniform( Matrix4f transform, int tboUniform ) { MATRIX_BUFFER.rewind(); transform.store( MATRIX_BUFFER ); MATRIX_BUFFER.rewind(); RenderSystem.glUniformMatrix4( uniformMv, false, MATRIX_BUFFER ); - RenderSystem.glUniform1i( uniformWidth, width ); - RenderSystem.glUniform1i( uniformHeight, height ); - - PALETTE_BUFFER.rewind(); - for( int i = 0; i < 16; i++ ) - { - double[] colour = palette.getColour( i ); - if( greyscale ) - { - float f = FixedWidthFontRenderer.toGreyscale( colour ); - PALETTE_BUFFER.put( f ).put( f ).put( f ); - } - else - { - PALETTE_BUFFER.put( (float) colour[0] ).put( (float) colour[1] ).put( (float) colour[2] ); - } - } - PALETTE_BUFFER.flip(); - RenderSystem.glUniform3( uniformPalette, PALETTE_BUFFER ); + GL31.glBindBufferBase( GL31.GL_UNIFORM_BUFFER, uniformMonitor, tboUniform ); } static boolean use() @@ -116,10 +104,9 @@ class MonitorTextureBufferShader uniformMv = getUniformLocation( program, "u_mv" ); uniformFont = getUniformLocation( program, "u_font" ); - uniformWidth = getUniformLocation( program, "u_width" ); - uniformHeight = getUniformLocation( program, "u_height" ); uniformTbo = getUniformLocation( program, "u_tbo" ); - uniformPalette = getUniformLocation( program, "u_palette" ); + uniformMonitor = GL31.glGetUniformBlockIndex( program, "u_monitor" ); + if( uniformMonitor == -1 ) throw new IllegalStateException( "Could not find uniformMonitor uniform." ); ComputerCraft.log.info( "Loaded monitor shader." ); return true; @@ -159,4 +146,50 @@ class MonitorTextureBufferShader if( uniform == -1 ) throw new IllegalStateException( "Cannot find uniform " + name ); return uniform; } + + public static void setTerminalData( ByteBuffer buffer, Terminal terminal ) + { + int width = terminal.getWidth(), height = terminal.getHeight(); + + int pos = 0; + for( int y = 0; y < height; y++ ) + { + TextBuffer text = terminal.getLine( y ), textColour = terminal.getTextColourLine( y ), background = terminal.getBackgroundColourLine( y ); + for( int x = 0; x < width; x++ ) + { + buffer.put( pos, (byte) (text.charAt( x ) & 0xFF) ); + buffer.put( pos + 1, (byte) getColour( textColour.charAt( x ), Colour.WHITE ) ); + buffer.put( pos + 2, (byte) getColour( background.charAt( x ), Colour.BLACK ) ); + pos += 3; + } + } + + buffer.limit( pos ); + } + + public static void setUniformData( ByteBuffer buffer, Terminal terminal, boolean greyscale ) + { + int pos = 0; + Palette palette = terminal.getPalette(); + for( int i = 0; i < 16; i++ ) + { + double[] colour = palette.getColour( i ); + if( greyscale ) + { + float f = FixedWidthFontRenderer.toGreyscale( colour ); + buffer.putFloat( pos, f ).putFloat( pos + 4, f ).putFloat( pos + 8, f ); + } + else + { + buffer.putFloat( pos, (float) colour[0] ).putFloat( pos + 4, (float) colour[1] ).putFloat( pos + 8, (float) colour[2] ); + } + + pos += 4 * 4; // std140 requires these are 4-wide + } + + int width = terminal.getWidth(), height = terminal.getHeight(); + buffer.putInt( pos, width ).putInt( pos + 4, height ); + + buffer.limit( UNIFORM_SIZE ); + } } diff --git a/src/main/java/dan200/computercraft/client/render/TileEntityMonitorRenderer.java b/src/main/java/dan200/computercraft/client/render/TileEntityMonitorRenderer.java index c2306bc68..8dcafcc89 100644 --- a/src/main/java/dan200/computercraft/client/render/TileEntityMonitorRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/TileEntityMonitorRenderer.java @@ -14,11 +14,9 @@ import dan200.computercraft.client.render.text.FixedWidthFontRenderer; import dan200.computercraft.client.util.DirectBuffers; import dan200.computercraft.client.util.DirectVertexBuffer; import dan200.computercraft.core.terminal.Terminal; -import dan200.computercraft.core.terminal.TextBuffer; import dan200.computercraft.shared.peripheral.monitor.ClientMonitor; import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer; import dan200.computercraft.shared.peripheral.monitor.TileMonitor; -import dan200.computercraft.shared.util.Colour; import dan200.computercraft.shared.util.DirectionUtil; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -39,7 +37,8 @@ import org.lwjgl.opengl.GL31; import javax.annotation.Nonnull; import java.nio.ByteBuffer; -import static dan200.computercraft.client.render.text.FixedWidthFontRenderer.*; +import static dan200.computercraft.client.render.text.FixedWidthFontRenderer.FONT_HEIGHT; +import static dan200.computercraft.client.render.text.FixedWidthFontRenderer.FONT_WIDTH; public class TileEntityMonitorRenderer extends TileEntityRenderer { @@ -172,22 +171,13 @@ public class TileEntityMonitorRenderer extends TileEntityRenderer if( redraw ) { - ByteBuffer monitorBuffer = getBuffer( width * height * 3 ); - for( int y = 0; y < height; y++ ) - { - TextBuffer text = terminal.getLine( y ), textColour = terminal.getTextColourLine( y ), background = terminal.getBackgroundColourLine( y ); - for( int x = 0; x < width; x++ ) - { - monitorBuffer.put( (byte) (text.charAt( x ) & 0xFF) ); - monitorBuffer.put( (byte) getColour( textColour.charAt( x ), Colour.WHITE ) ); - monitorBuffer.put( (byte) getColour( background.charAt( x ), Colour.BLACK ) ); - } - } - monitorBuffer.flip(); + ByteBuffer terminalBuffer = getBuffer( width * height * 3 ); + MonitorTextureBufferShader.setTerminalData( terminalBuffer, terminal ); + DirectBuffers.setBufferData( GL31.GL_TEXTURE_BUFFER, monitor.tboBuffer, terminalBuffer, GL20.GL_STATIC_DRAW ); - GlStateManager._glBindBuffer( GL31.GL_TEXTURE_BUFFER, monitor.tboBuffer ); - GlStateManager._glBufferData( GL31.GL_TEXTURE_BUFFER, monitorBuffer, GL20.GL_STATIC_DRAW ); - GlStateManager._glBindBuffer( GL31.GL_TEXTURE_BUFFER, 0 ); + ByteBuffer uniformBuffer = getBuffer( MonitorTextureBufferShader.UNIFORM_SIZE ); + MonitorTextureBufferShader.setUniformData( uniformBuffer, terminal, !monitor.isColour() ); + DirectBuffers.setBufferData( GL31.GL_UNIFORM_BUFFER, monitor.tboUniform, uniformBuffer, GL20.GL_STATIC_DRAW ); } // Nobody knows what they're doing! @@ -195,7 +185,7 @@ public class TileEntityMonitorRenderer extends TileEntityRenderer GL11.glBindTexture( GL31.GL_TEXTURE_BUFFER, monitor.tboTexture ); GlStateManager._activeTexture( GL13.GL_TEXTURE0 ); - MonitorTextureBufferShader.setupUniform( matrix, width, height, terminal.getPalette(), !monitor.isColour() ); + MonitorTextureBufferShader.setupUniform( matrix, monitor.tboUniform ); Tessellator tessellator = Tessellator.getInstance(); BufferBuilder buffer = tessellator.getBuilder(); diff --git a/src/main/java/dan200/computercraft/shared/peripheral/monitor/ClientMonitor.java b/src/main/java/dan200/computercraft/shared/peripheral/monitor/ClientMonitor.java index 0c383b502..186d63c76 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/monitor/ClientMonitor.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/monitor/ClientMonitor.java @@ -7,6 +7,7 @@ package dan200.computercraft.shared.peripheral.monitor; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; +import dan200.computercraft.client.util.DirectBuffers; import dan200.computercraft.client.util.DirectVertexBuffer; import dan200.computercraft.shared.common.ClientTerminal; import net.minecraft.util.math.BlockPos; @@ -32,6 +33,7 @@ public final class ClientMonitor extends ClientTerminal public int tboBuffer; public int tboTexture; + public int tboUniform; public DirectVertexBuffer buffer; public ClientMonitor( boolean colour, TileMonitor origin ) @@ -63,15 +65,15 @@ public final class ClientMonitor extends ClientTerminal deleteBuffers(); - tboBuffer = GlStateManager._glGenBuffers(); - GlStateManager._glBindBuffer( GL31.GL_TEXTURE_BUFFER, tboBuffer ); - GL15.glBufferData( GL31.GL_TEXTURE_BUFFER, 0, GL15.GL_STATIC_DRAW ); + tboBuffer = DirectBuffers.createBuffer(); + DirectBuffers.setEmptyBufferData( GL31.GL_TEXTURE_BUFFER, tboBuffer, GL15.GL_STATIC_DRAW ); tboTexture = GlStateManager._genTexture(); GL11.glBindTexture( GL31.GL_TEXTURE_BUFFER, tboTexture ); GL31.glTexBuffer( GL31.GL_TEXTURE_BUFFER, GL30.GL_R8UI, tboBuffer ); GL11.glBindTexture( GL31.GL_TEXTURE_BUFFER, 0 ); - GlStateManager._glBindBuffer( GL31.GL_TEXTURE_BUFFER, 0 ); + tboUniform = DirectBuffers.createBuffer(); + DirectBuffers.setEmptyBufferData( GL31.GL_UNIFORM_BUFFER, tboUniform, GL15.GL_STATIC_DRAW ); addMonitor(); return true; @@ -113,6 +115,12 @@ public final class ClientMonitor extends ClientTerminal tboTexture = 0; } + if( tboUniform != 0 ) + { + RenderSystem.glDeleteBuffers( tboUniform ); + tboUniform = 0; + } + if( buffer != null ) { buffer.close(); diff --git a/src/main/resources/assets/computercraft/shaders/monitor.frag b/src/main/resources/assets/computercraft/shaders/monitor.frag index f19a6a9eb..09408ff1c 100644 --- a/src/main/resources/assets/computercraft/shaders/monitor.frag +++ b/src/main/resources/assets/computercraft/shaders/monitor.frag @@ -4,10 +4,13 @@ #define FONT_HEIGHT 9.0 uniform sampler2D u_font; -uniform int u_width; -uniform int u_height; uniform usamplerBuffer u_tbo; -uniform vec3 u_palette[16]; + +layout(std140) uniform u_monitor { + vec3 u_palette[16]; + int u_width; + int u_height; +}; in vec2 f_pos;