renderer: clear renderstate memory periodically
parent
2ecaf4a595
commit
82f5c1a13c
|
|
@ -206,6 +206,12 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
|||
/// The render state we update per loop.
|
||||
terminal_state: terminal.RenderState = .empty,
|
||||
|
||||
/// The number of frames since the last terminal state reset.
|
||||
/// We reset the terminal state after ~100,000 frames (about 10 to
|
||||
/// 15 minutes at 120Hz) to prevent wasted memory buildup from
|
||||
/// a large screen.
|
||||
terminal_state_frame_count: usize = 0,
|
||||
|
||||
/// Swap chain which maintains multiple copies of the state needed to
|
||||
/// render a frame, so that we can start building the next frame while
|
||||
/// the previous frame is still being processed on the GPU.
|
||||
|
|
@ -1062,6 +1068,18 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
|||
state: *renderer.State,
|
||||
cursor_blink_visible: bool,
|
||||
) !void {
|
||||
// We fully deinit and reset the terminal state every so often
|
||||
// so that a particularly large terminal state doesn't cause
|
||||
// the renderer to hold on to retained memory.
|
||||
//
|
||||
// Frame count is ~12 minutes at 120Hz.
|
||||
const max_terminal_state_frame_count = 100_000;
|
||||
if (self.terminal_state_frame_count >= max_terminal_state_frame_count) {
|
||||
self.terminal_state.deinit(self.alloc);
|
||||
self.terminal_state = .empty;
|
||||
}
|
||||
self.terminal_state_frame_count += 1;
|
||||
|
||||
// Create an arena for all our temporary allocations while rebuilding
|
||||
var arena = ArenaAllocator.init(self.alloc);
|
||||
defer arena.deinit();
|
||||
|
|
|
|||
|
|
@ -30,6 +30,19 @@ const Terminal = @import("Terminal.zig");
|
|||
/// Rather than a generic clone that tries to clone all screen state per call
|
||||
/// (within a region), a stateful approach that optimizes for only what a
|
||||
/// renderer needs to do makes more sense.
|
||||
///
|
||||
/// To use this, initialize the render state to empty, then call `update`
|
||||
/// on each frame to update the state to the latest terminal state.
|
||||
///
|
||||
/// var state: RenderState = .empty;
|
||||
/// defer state.deinit(alloc);
|
||||
/// state.update(alloc, &terminal);
|
||||
///
|
||||
/// Note: the render state retains as much memory as possible between updates
|
||||
/// to prevent future allocations. If a very large frame is rendered once,
|
||||
/// the render state will retain that much memory until deinit. To avoid
|
||||
/// waste, it is recommended that the caller `deinit` and start with an
|
||||
/// empty render state every so often.
|
||||
pub const RenderState = struct {
|
||||
/// The current screen dimensions. It is possible that these don't match
|
||||
/// the renderer's current dimensions in grid cells because resizing
|
||||
|
|
|
|||
Loading…
Reference in New Issue