1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2024-12-14 04:00:30 +00:00

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 :).
This commit is contained in:
Jonathan Coates 2022-04-26 19:14:37 +01:00
parent 78aa757549
commit 77a00b14ae
No known key found for this signature in database
GPG Key ID: B9E431FF07C98D06
4 changed files with 87 additions and 53 deletions

View File

@ -10,61 +10,49 @@ import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import dan200.computercraft.ComputerCraft; import dan200.computercraft.ComputerCraft;
import dan200.computercraft.client.render.text.FixedWidthFontRenderer; 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 dan200.computercraft.shared.util.Palette;
import net.minecraft.client.renderer.texture.TextureUtil; import net.minecraft.client.renderer.texture.TextureUtil;
import net.minecraft.util.math.vector.Matrix4f; import net.minecraft.util.math.vector.Matrix4f;
import org.lwjgl.BufferUtils; import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL13; import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL31;
import java.io.InputStream; import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
import static dan200.computercraft.client.render.text.FixedWidthFontRenderer.getColour;
class MonitorTextureBufferShader class MonitorTextureBufferShader
{ {
public static final int UNIFORM_SIZE = 4 * 4 * 16 + 4 + 4;
static final int TEXTURE_INDEX = GL13.GL_TEXTURE3; static final int TEXTURE_INDEX = GL13.GL_TEXTURE3;
private static final FloatBuffer MATRIX_BUFFER = BufferUtils.createFloatBuffer( 16 ); 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 uniformMv;
private static int uniformFont; private static int uniformFont;
private static int uniformWidth;
private static int uniformHeight;
private static int uniformTbo; private static int uniformTbo;
private static int uniformPalette; private static int uniformMonitor;
private static boolean initialised; private static boolean initialised;
private static boolean ok; private static boolean ok;
private static int program; 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(); MATRIX_BUFFER.rewind();
transform.store( MATRIX_BUFFER ); transform.store( MATRIX_BUFFER );
MATRIX_BUFFER.rewind(); MATRIX_BUFFER.rewind();
RenderSystem.glUniformMatrix4( uniformMv, false, MATRIX_BUFFER ); RenderSystem.glUniformMatrix4( uniformMv, false, MATRIX_BUFFER );
RenderSystem.glUniform1i( uniformWidth, width ); GL31.glBindBufferBase( GL31.GL_UNIFORM_BUFFER, uniformMonitor, tboUniform );
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 );
} }
static boolean use() static boolean use()
@ -116,10 +104,9 @@ class MonitorTextureBufferShader
uniformMv = getUniformLocation( program, "u_mv" ); uniformMv = getUniformLocation( program, "u_mv" );
uniformFont = getUniformLocation( program, "u_font" ); uniformFont = getUniformLocation( program, "u_font" );
uniformWidth = getUniformLocation( program, "u_width" );
uniformHeight = getUniformLocation( program, "u_height" );
uniformTbo = getUniformLocation( program, "u_tbo" ); 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." ); ComputerCraft.log.info( "Loaded monitor shader." );
return true; return true;
@ -159,4 +146,50 @@ class MonitorTextureBufferShader
if( uniform == -1 ) throw new IllegalStateException( "Cannot find uniform " + name ); if( uniform == -1 ) throw new IllegalStateException( "Cannot find uniform " + name );
return uniform; 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 );
}
} }

View File

@ -14,11 +14,9 @@ import dan200.computercraft.client.render.text.FixedWidthFontRenderer;
import dan200.computercraft.client.util.DirectBuffers; import dan200.computercraft.client.util.DirectBuffers;
import dan200.computercraft.client.util.DirectVertexBuffer; import dan200.computercraft.client.util.DirectVertexBuffer;
import dan200.computercraft.core.terminal.Terminal; 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.ClientMonitor;
import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer; import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer;
import dan200.computercraft.shared.peripheral.monitor.TileMonitor; import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
import dan200.computercraft.shared.util.Colour;
import dan200.computercraft.shared.util.DirectionUtil; import dan200.computercraft.shared.util.DirectionUtil;
import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer;
@ -39,7 +37,8 @@ import org.lwjgl.opengl.GL31;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.nio.ByteBuffer; 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<TileMonitor> public class TileEntityMonitorRenderer extends TileEntityRenderer<TileMonitor>
{ {
@ -172,22 +171,13 @@ public class TileEntityMonitorRenderer extends TileEntityRenderer<TileMonitor>
if( redraw ) if( redraw )
{ {
ByteBuffer monitorBuffer = getBuffer( width * height * 3 ); ByteBuffer terminalBuffer = getBuffer( width * height * 3 );
for( int y = 0; y < height; y++ ) MonitorTextureBufferShader.setTerminalData( terminalBuffer, terminal );
{ DirectBuffers.setBufferData( GL31.GL_TEXTURE_BUFFER, monitor.tboBuffer, terminalBuffer, GL20.GL_STATIC_DRAW );
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();
GlStateManager._glBindBuffer( GL31.GL_TEXTURE_BUFFER, monitor.tboBuffer ); ByteBuffer uniformBuffer = getBuffer( MonitorTextureBufferShader.UNIFORM_SIZE );
GlStateManager._glBufferData( GL31.GL_TEXTURE_BUFFER, monitorBuffer, GL20.GL_STATIC_DRAW ); MonitorTextureBufferShader.setUniformData( uniformBuffer, terminal, !monitor.isColour() );
GlStateManager._glBindBuffer( GL31.GL_TEXTURE_BUFFER, 0 ); DirectBuffers.setBufferData( GL31.GL_UNIFORM_BUFFER, monitor.tboUniform, uniformBuffer, GL20.GL_STATIC_DRAW );
} }
// Nobody knows what they're doing! // Nobody knows what they're doing!
@ -195,7 +185,7 @@ public class TileEntityMonitorRenderer extends TileEntityRenderer<TileMonitor>
GL11.glBindTexture( GL31.GL_TEXTURE_BUFFER, monitor.tboTexture ); GL11.glBindTexture( GL31.GL_TEXTURE_BUFFER, monitor.tboTexture );
GlStateManager._activeTexture( GL13.GL_TEXTURE0 ); GlStateManager._activeTexture( GL13.GL_TEXTURE0 );
MonitorTextureBufferShader.setupUniform( matrix, width, height, terminal.getPalette(), !monitor.isColour() ); MonitorTextureBufferShader.setupUniform( matrix, monitor.tboUniform );
Tessellator tessellator = Tessellator.getInstance(); Tessellator tessellator = Tessellator.getInstance();
BufferBuilder buffer = tessellator.getBuilder(); BufferBuilder buffer = tessellator.getBuilder();

View File

@ -7,6 +7,7 @@ package dan200.computercraft.shared.peripheral.monitor;
import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import dan200.computercraft.client.util.DirectBuffers;
import dan200.computercraft.client.util.DirectVertexBuffer; import dan200.computercraft.client.util.DirectVertexBuffer;
import dan200.computercraft.shared.common.ClientTerminal; import dan200.computercraft.shared.common.ClientTerminal;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@ -32,6 +33,7 @@ public final class ClientMonitor extends ClientTerminal
public int tboBuffer; public int tboBuffer;
public int tboTexture; public int tboTexture;
public int tboUniform;
public DirectVertexBuffer buffer; public DirectVertexBuffer buffer;
public ClientMonitor( boolean colour, TileMonitor origin ) public ClientMonitor( boolean colour, TileMonitor origin )
@ -63,15 +65,15 @@ public final class ClientMonitor extends ClientTerminal
deleteBuffers(); deleteBuffers();
tboBuffer = GlStateManager._glGenBuffers(); tboBuffer = DirectBuffers.createBuffer();
GlStateManager._glBindBuffer( GL31.GL_TEXTURE_BUFFER, tboBuffer ); DirectBuffers.setEmptyBufferData( GL31.GL_TEXTURE_BUFFER, tboBuffer, GL15.GL_STATIC_DRAW );
GL15.glBufferData( GL31.GL_TEXTURE_BUFFER, 0, GL15.GL_STATIC_DRAW );
tboTexture = GlStateManager._genTexture(); tboTexture = GlStateManager._genTexture();
GL11.glBindTexture( GL31.GL_TEXTURE_BUFFER, tboTexture ); GL11.glBindTexture( GL31.GL_TEXTURE_BUFFER, tboTexture );
GL31.glTexBuffer( GL31.GL_TEXTURE_BUFFER, GL30.GL_R8UI, tboBuffer ); GL31.glTexBuffer( GL31.GL_TEXTURE_BUFFER, GL30.GL_R8UI, tboBuffer );
GL11.glBindTexture( GL31.GL_TEXTURE_BUFFER, 0 ); 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(); addMonitor();
return true; return true;
@ -113,6 +115,12 @@ public final class ClientMonitor extends ClientTerminal
tboTexture = 0; tboTexture = 0;
} }
if( tboUniform != 0 )
{
RenderSystem.glDeleteBuffers( tboUniform );
tboUniform = 0;
}
if( buffer != null ) if( buffer != null )
{ {
buffer.close(); buffer.close();

View File

@ -4,10 +4,13 @@
#define FONT_HEIGHT 9.0 #define FONT_HEIGHT 9.0
uniform sampler2D u_font; uniform sampler2D u_font;
uniform int u_width;
uniform int u_height;
uniform usamplerBuffer u_tbo; 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; in vec2 f_pos;