From ced8776120d2dbd7ebeab6d538a9958e44fb44ff Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Thu, 25 Apr 2024 19:16:40 -0700 Subject: [PATCH] renderer/metal: grid pos for bg/text should be ushort2 This saves 50% memory per vertex. --- src/renderer/Metal.zig | 33 +++++++++++++++------------------ src/renderer/State.zig | 12 ++++++++---- src/renderer/metal/api.zig | 1 + src/renderer/metal/shaders.zig | 8 ++++---- src/renderer/shaders/cell.metal | 8 ++++---- 5 files changed, 32 insertions(+), 30 deletions(-) diff --git a/src/renderer/Metal.zig b/src/renderer/Metal.zig index 3636d0eb3..19d73f3d4 100644 --- a/src/renderer/Metal.zig +++ b/src/renderer/Metal.zig @@ -1751,8 +1751,8 @@ fn rebuildCells( // Determine our x/y range for preedit. We don't want to render anything // here because we will render the preedit separately. const preedit_range: ?struct { - y: usize, - x: [2]usize, + y: terminal.size.CellCountInt, + x: [2]terminal.size.CellCountInt, cp_offset: usize, } = if (preedit) |preedit_v| preedit: { const range = preedit_v.range(screen.cursor.x, screen.pages.cols - 1); @@ -1770,7 +1770,7 @@ fn rebuildCells( // Build each cell var row_it = screen.pages.rowIterator(.right_down, .{ .viewport = .{} }, null); - var y: usize = 0; + var y: terminal.size.CellCountInt = 0; while (row_it.next()) |row| { defer y += 1; @@ -1809,7 +1809,7 @@ fn rebuildCells( const screen_cell = row.cells(.all)[screen.cursor.x]; const x = screen.cursor.x - @intFromBool(screen_cell.wide == .spacer_tail); for (self.cells_text.items[start_i..]) |cell| { - if (cell.grid_pos[0] == @as(f32, @floatFromInt(x)) and + if (cell.grid_pos[0] == x and (cell.mode == .fg or cell.mode == .fg_color)) { cursor_cell = cell; @@ -1929,8 +1929,8 @@ fn updateCell( palette: *const terminal.color.Palette, shaper_cell: font.shape.Cell, shaper_run: font.shape.TextRun, - x: usize, - y: usize, + x: terminal.size.CellCountInt, + y: terminal.size.CellCountInt, ) !bool { const BgFg = struct { /// Background is optional because in un-inverted mode @@ -2031,7 +2031,7 @@ fn updateCell( self.cells_bg.appendAssumeCapacity(.{ .mode = .rgb, - .grid_pos = .{ @as(f32, @floatFromInt(x)), @as(f32, @floatFromInt(y)) }, + .grid_pos = .{ x, y }, .cell_width = cell.gridWidth(), .color = .{ rgb.r, rgb.g, rgb.b, bg_alpha }, }); @@ -2068,7 +2068,7 @@ fn updateCell( self.cells_text.appendAssumeCapacity(.{ .mode = mode, - .grid_pos = .{ @as(f32, @floatFromInt(x)), @as(f32, @floatFromInt(y)) }, + .grid_pos = .{ x, y }, .cell_width = cell.gridWidth(), .color = .{ colors.fg.r, colors.fg.g, colors.fg.b, alpha }, .bg_color = bg, @@ -2105,7 +2105,7 @@ fn updateCell( self.cells_text.appendAssumeCapacity(.{ .mode = .fg, - .grid_pos = .{ @as(f32, @floatFromInt(x)), @as(f32, @floatFromInt(y)) }, + .grid_pos = .{ x, y }, .cell_width = cell.gridWidth(), .color = .{ color.r, color.g, color.b, alpha }, .bg_color = bg, @@ -2128,7 +2128,7 @@ fn updateCell( self.cells_text.appendAssumeCapacity(.{ .mode = .fg, - .grid_pos = .{ @as(f32, @floatFromInt(x)), @as(f32, @floatFromInt(y)) }, + .grid_pos = .{ x, y }, .cell_width = cell.gridWidth(), .color = .{ colors.fg.r, colors.fg.g, colors.fg.b, alpha }, .bg_color = bg, @@ -2188,10 +2188,7 @@ fn addCursor( self.cells_text.appendAssumeCapacity(.{ .mode = .fg, - .grid_pos = .{ - @as(f32, @floatFromInt(x)), - @as(f32, @floatFromInt(screen.cursor.y)), - }, + .grid_pos = .{ x, screen.cursor.y }, .cell_width = if (wide) 2 else 1, .color = .{ color.r, color.g, color.b, alpha }, .bg_color = .{ 0, 0, 0, 0 }, @@ -2206,8 +2203,8 @@ fn addCursor( fn addPreeditCell( self: *Metal, cp: renderer.State.Preedit.Codepoint, - x: usize, - y: usize, + x: terminal.size.CellCountInt, + y: terminal.size.CellCountInt, ) !void { // Preedit is rendered inverted const bg = self.foreground_color; @@ -2232,7 +2229,7 @@ fn addPreeditCell( // Add our opaque background cell self.cells_bg.appendAssumeCapacity(.{ .mode = .rgb, - .grid_pos = .{ @as(f32, @floatFromInt(x)), @as(f32, @floatFromInt(y)) }, + .grid_pos = .{ x, y }, .cell_width = if (cp.wide) 2 else 1, .color = .{ bg.r, bg.g, bg.b, 255 }, }); @@ -2240,7 +2237,7 @@ fn addPreeditCell( // Add our text self.cells_text.appendAssumeCapacity(.{ .mode = .fg, - .grid_pos = .{ @as(f32, @floatFromInt(x)), @as(f32, @floatFromInt(y)) }, + .grid_pos = .{ x, y }, .cell_width = if (cp.wide) 2 else 1, .color = .{ fg.r, fg.g, fg.b, 255 }, .bg_color = .{ bg.r, bg.g, bg.b, 255 }, diff --git a/src/renderer/State.zig b/src/renderer/State.zig index 6bff5b219..8a11a7403 100644 --- a/src/renderer/State.zig +++ b/src/renderer/State.zig @@ -78,9 +78,13 @@ pub const Preedit = struct { /// Range returns the start and end x position of the preedit text /// along with any codepoint offset necessary to fit the preedit /// into the available space. - pub fn range(self: *const Preedit, start: usize, max: usize) struct { - start: usize, - end: usize, + pub fn range( + self: *const Preedit, + start: terminal.size.CellCountInt, + max: terminal.size.CellCountInt, + ) struct { + start: terminal.size.CellCountInt, + end: terminal.size.CellCountInt, cp_offset: usize, } { // If our width is greater than the number of cells we have @@ -92,7 +96,7 @@ pub const Preedit = struct { // Rebuild our width in reverse order. This is because we want // to offset by the end cells, not the start cells (if we have to). - var w: usize = 0; + var w: terminal.size.CellCountInt = 0; for (0..self.codepoints.len) |i| { const reverse_i = self.codepoints.len - i - 1; const cp = self.codepoints[reverse_i]; diff --git a/src/renderer/metal/api.zig b/src/renderer/metal/api.zig index 0421a34a2..3ec04e367 100644 --- a/src/renderer/metal/api.zig +++ b/src/renderer/metal/api.zig @@ -50,6 +50,7 @@ pub const MTLIndexType = enum(c_ulong) { /// https://developer.apple.com/documentation/metal/mtlvertexformat?language=objc pub const MTLVertexFormat = enum(c_ulong) { uchar4 = 3, + ushort2 = 13, float2 = 29, float4 = 31, int2 = 33, diff --git a/src/renderer/metal/shaders.zig b/src/renderer/metal/shaders.zig index 40e048984..f764e4909 100644 --- a/src/renderer/metal/shaders.zig +++ b/src/renderer/metal/shaders.zig @@ -287,7 +287,7 @@ fn initPostPipeline( /// This is a single parameter for the terminal cell shader. pub const CellText = extern struct { mode: Mode, - grid_pos: [2]f32, + grid_pos: [2]u16, glyph_pos: [2]u32 = .{ 0, 0 }, glyph_size: [2]u32 = .{ 0, 0 }, glyph_offset: [2]i32 = .{ 0, 0 }, @@ -363,7 +363,7 @@ fn initCellTextPipeline(device: objc.Object, library: objc.Object) !objc.Object .{@as(c_ulong, 1)}, ); - attr.setProperty("format", @intFromEnum(mtl.MTLVertexFormat.float2)); + attr.setProperty("format", @intFromEnum(mtl.MTLVertexFormat.ushort2)); attr.setProperty("offset", @as(c_ulong, @offsetOf(CellText, "grid_pos"))); attr.setProperty("bufferIndex", @as(c_ulong, 0)); } @@ -505,7 +505,7 @@ fn initCellTextPipeline(device: objc.Object, library: objc.Object) !objc.Object /// This is a single parameter for the cell bg shader. pub const CellBg = extern struct { mode: Mode, - grid_pos: [2]f32, + grid_pos: [2]u16, color: [4]u8, cell_width: u8, @@ -574,7 +574,7 @@ fn initCellBgPipeline(device: objc.Object, library: objc.Object) !objc.Object { .{@as(c_ulong, 1)}, ); - attr.setProperty("format", @intFromEnum(mtl.MTLVertexFormat.float2)); + attr.setProperty("format", @intFromEnum(mtl.MTLVertexFormat.ushort2)); attr.setProperty("offset", @as(c_ulong, @offsetOf(CellBg, "grid_pos"))); attr.setProperty("bufferIndex", @as(c_ulong, 0)); } diff --git a/src/renderer/shaders/cell.metal b/src/renderer/shaders/cell.metal index dd9ace86a..3aae45ef5 100644 --- a/src/renderer/shaders/cell.metal +++ b/src/renderer/shaders/cell.metal @@ -70,7 +70,7 @@ struct CellBgVertexIn { uint8_t mode [[attribute(0)]]; // The grid coordinates (x, y) where x < columns and y < rows - float2 grid_pos [[attribute(1)]]; + ushort2 grid_pos [[attribute(1)]]; // The color. For BG modes, this is the bg color, for FG modes this is // the text color. For styles, this is the color of the style. @@ -90,7 +90,7 @@ vertex CellBgVertexOut cell_bg_vertex(unsigned int vid [[vertex_id]], constant Uniforms& uniforms [[buffer(1)]]) { // Convert the grid x,y into world space x, y by accounting for cell size - float2 cell_pos = uniforms.cell_size * input.grid_pos; + float2 cell_pos = uniforms.cell_size * float2(input.grid_pos); // Scaled cell size for the cell width float2 cell_size_scaled = uniforms.cell_size; @@ -144,7 +144,7 @@ struct CellTextVertexIn { uint8_t mode [[attribute(0)]]; // The grid coordinates (x, y) where x < columns and y < rows - float2 grid_pos [[attribute(1)]]; + ushort2 grid_pos [[attribute(1)]]; // The width of the cell in cells (i.e. 2 for double-wide). uint8_t cell_width [[attribute(6)]]; @@ -180,7 +180,7 @@ vertex CellTextVertexOut cell_text_vertex(unsigned int vid [[vertex_id]], constant Uniforms& uniforms [[buffer(1)]]) { // Convert the grid x,y into world space x, y by accounting for cell size - float2 cell_pos = uniforms.cell_size * input.grid_pos; + float2 cell_pos = uniforms.cell_size * float2(input.grid_pos); // Scaled cell size for the cell width float2 cell_size_scaled = uniforms.cell_size;