From 6b3cb69101a94345f9bf80bb10635c49db5c9724 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 4 May 2024 19:05:22 -0700 Subject: [PATCH] renderer/metal: clean up some unnecessary state around rebuilds --- src/renderer/Metal.zig | 51 ++++++++++++++++++++++--------------- src/renderer/metal/cell.zig | 7 +++++ 2 files changed, 37 insertions(+), 21 deletions(-) diff --git a/src/renderer/Metal.zig b/src/renderer/Metal.zig index 6c242cf73..72a0ab19c 100644 --- a/src/renderer/Metal.zig +++ b/src/renderer/Metal.zig @@ -98,9 +98,6 @@ current_background_color: terminal.color.RGB, /// cells goes into a separate shader. cells: mtl_cell.Contents, -/// If this is true, we do a full cell rebuild on the next frame. -cells_rebuild: bool = true, - /// Set to true after rebuildCells is called. This can be used /// to determine if any possible changes have been made to the /// cells for the draw call. @@ -818,6 +815,9 @@ pub fn updateFrame( preedit: ?renderer.State.Preedit, cursor_style: ?renderer.CursorStyle, color_palette: terminal.color.Palette, + + /// If true, rebuild the full screen. + full_rebuild: bool, }; // Update all our data as tightly as possible within the mutex. @@ -888,16 +888,20 @@ pub fn updateFrame( // If we have any terminal dirty flags set then we need to rebuild // the entire screen. This can be optimized in the future. - { - const Int = @typeInfo(terminal.Terminal.Dirty).Struct.backing_integer.?; - const v: Int = @bitCast(state.terminal.flags.dirty); - if (v > 0) self.cells_rebuild = true; - } - { - const Int = @typeInfo(terminal.Screen.Dirty).Struct.backing_integer.?; - const v: Int = @bitCast(state.terminal.screen.dirty); - if (v > 0) self.cells_rebuild = true; - } + const full_rebuild: bool = rebuild: { + { + const Int = @typeInfo(terminal.Terminal.Dirty).Struct.backing_integer.?; + const v: Int = @bitCast(state.terminal.flags.dirty); + if (v > 0) break :rebuild true; + } + { + const Int = @typeInfo(terminal.Screen.Dirty).Struct.backing_integer.?; + const v: Int = @bitCast(state.terminal.screen.dirty); + if (v > 0) break :rebuild true; + } + + break :rebuild false; + }; // Reset the dirty flags in the terminal and screen. We assume // that our rebuild will be successful since so we optimize for @@ -923,6 +927,7 @@ pub fn updateFrame( .preedit = preedit, .cursor_style = cursor_style, .color_palette = state.terminal.color_palette.colors, + .full_rebuild = full_rebuild, }; }; defer { @@ -932,6 +937,7 @@ pub fn updateFrame( // Build our GPU cells try self.rebuildCells( + critical.full_rebuild, &critical.screen, critical.mouse, critical.preedit, @@ -1799,6 +1805,7 @@ pub fn setScreenSize( /// memory and doesn't touch the GPU. fn rebuildCells( self: *Metal, + rebuild: bool, screen: *terminal.Screen, mouse: renderer.State.Mouse, preedit: ?renderer.State.Preedit, @@ -1839,6 +1846,9 @@ fn rebuildCells( }; } else null; + // If we are doing a full rebuild, then we clear the entire cell buffer. + if (rebuild) self.cells.reset(); + // Go row-by-row to build the cells. We go row by row because we do // font shaping by row. In the future, we will also do dirty tracking // by row. @@ -1847,12 +1857,14 @@ fn rebuildCells( while (row_it.next()) |row| { y = y - 1; - // Only rebuild if we are doing a full rebuild or this row is dirty. - // if (row.isDirty()) std.log.warn("dirty y={}", .{y}); - if (!self.cells_rebuild and !row.isDirty()) continue; + if (!rebuild) { + // Only rebuild if we are doing a full rebuild or this row is dirty. + // if (row.isDirty()) std.log.warn("dirty y={}", .{y}); + if (!row.isDirty()) continue; - // If we're rebuilding a row, then we always clear the cells - self.cells.clear(y); + // Clear the cells if the row is dirty + self.cells.clear(y); + } // True if we want to do font shaping around the cursor. We want to // do font shaping as long as the cursor is enabled. @@ -1996,9 +2008,6 @@ fn rebuildCells( } } - // We always mark our rebuild flag as false since we're done. - self.cells_rebuild = false; - // Update that our cells rebuilt self.cells_rebuilt = true; diff --git a/src/renderer/metal/cell.zig b/src/renderer/metal/cell.zig index f6ee1a955..c0d7f56a3 100644 --- a/src/renderer/metal/cell.zig +++ b/src/renderer/metal/cell.zig @@ -124,6 +124,13 @@ pub const Contents = struct { self.text.shrinkAndFree(alloc, text_reserved_len); } + /// Reset the cell contents to an empty state without resizing. + pub fn reset(self: *Contents) void { + @memset(self.map, .{}); + self.bgs.clearRetainingCapacity(); + self.text.shrinkRetainingCapacity(text_reserved_len); + } + /// Returns the slice of fg cell contents to sync with the GPU. pub fn fgCells(self: *const Contents) []const mtl_shaders.CellText { const start: usize = if (self.cursor) 0 else 1;