mirror of
https://github.com/wez/wezterm.git
synced 2024-11-10 15:04:32 +03:00
dynamically allocate quads as needed
This removes the pre-allocated (at resize) number of quads and replaces it with a dynamic mechanism that tracks how many quads are needed for a frame and then will re-allocate and re-render when there weren't enough. We start with 1024 quads and try to allocate in multiples of 1024 quads. refs: #986
This commit is contained in:
parent
6a84f051b6
commit
89586d658e
@ -22,10 +22,16 @@ pub struct MappedQuads<'a> {
|
||||
impl<'a> MappedQuads<'a> {
|
||||
pub fn allocate<'b>(&'b mut self) -> anyhow::Result<Quad<'b>> {
|
||||
let idx = *self.next;
|
||||
if idx >= self.capacity {
|
||||
anyhow::bail!("not enough quads! do something like OutOfTextureSpace");
|
||||
}
|
||||
*self.next += 1;
|
||||
let idx = if idx >= self.capacity {
|
||||
// We don't have enough quads, so we'll keep re-using
|
||||
// the first quad until we reach the end of the render
|
||||
// pass, at which point we'll detect this condition
|
||||
// and re-allocate the quads.
|
||||
0
|
||||
} else {
|
||||
idx
|
||||
};
|
||||
|
||||
let idx = idx * VERTICES_PER_CELL;
|
||||
let mut quad = Quad {
|
||||
@ -52,6 +58,15 @@ impl TripleVertexBuffer {
|
||||
*self.next_quad.borrow_mut() = 0;
|
||||
}
|
||||
|
||||
pub fn need_more_quads(&self) -> Option<usize> {
|
||||
let next = *self.next_quad.borrow();
|
||||
if next > self.capacity {
|
||||
Some(next)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn vertex_index_count(&self) -> (usize, usize) {
|
||||
let num_quads = *self.next_quad.borrow();
|
||||
(num_quads * VERTICES_PER_CELL, num_quads * INDICES_PER_CELL)
|
||||
@ -104,8 +119,6 @@ impl RenderState {
|
||||
fonts: &Rc<FontConfiguration>,
|
||||
metrics: &RenderMetrics,
|
||||
mut atlas_size: usize,
|
||||
pixel_width: usize,
|
||||
pixel_height: usize,
|
||||
) -> anyhow::Result<Self> {
|
||||
loop {
|
||||
let glyph_cache =
|
||||
@ -123,12 +136,7 @@ impl RenderState {
|
||||
// Last prog outputs srgb for gamma correction
|
||||
let img_prog = Self::compile_prog(&context, true, Self::img_shader)?;
|
||||
|
||||
let glyph_vertex_buffer = Self::compute_vertices(
|
||||
&context,
|
||||
metrics,
|
||||
pixel_width as f32,
|
||||
pixel_height as f32,
|
||||
)?;
|
||||
let glyph_vertex_buffer = Self::compute_vertices(&context, 1024)?;
|
||||
|
||||
return Ok(Self {
|
||||
context,
|
||||
@ -183,18 +191,8 @@ impl RenderState {
|
||||
anyhow::bail!("Failed to compile shaders: {}", errors.join("\n"))
|
||||
}
|
||||
|
||||
pub fn advise_of_window_size_change(
|
||||
&mut self,
|
||||
metrics: &RenderMetrics,
|
||||
pixel_width: usize,
|
||||
pixel_height: usize,
|
||||
) -> anyhow::Result<()> {
|
||||
let glyph_vertex_buffer = Self::compute_vertices(
|
||||
&self.context,
|
||||
metrics,
|
||||
pixel_width as f32,
|
||||
pixel_height as f32,
|
||||
)?;
|
||||
pub fn reallocate_quads(&mut self, num_quads: usize) -> anyhow::Result<()> {
|
||||
let glyph_vertex_buffer = Self::compute_vertices(&self.context, num_quads)?;
|
||||
|
||||
self.glyph_vertex_buffer = glyph_vertex_buffer;
|
||||
Ok(())
|
||||
@ -276,25 +274,8 @@ impl RenderState {
|
||||
/// let the GPU figure out the rest.
|
||||
fn compute_vertices(
|
||||
context: &Rc<GliumContext>,
|
||||
metrics: &RenderMetrics,
|
||||
width: f32,
|
||||
height: f32,
|
||||
num_quads: usize,
|
||||
) -> anyhow::Result<TripleVertexBuffer> {
|
||||
let cell_width = metrics.cell_size.width as f32;
|
||||
let cell_height = metrics.cell_size.height as f32;
|
||||
|
||||
let num_cols = width as usize / cell_width as usize;
|
||||
let num_rows = height as usize / cell_height as usize;
|
||||
|
||||
log::debug!(
|
||||
"compute_vertices {}x{} {}x{}",
|
||||
num_cols,
|
||||
num_rows,
|
||||
width,
|
||||
height,
|
||||
);
|
||||
|
||||
let num_quads = num_cols * num_rows + 2 /* bg image, scroll thumb */;
|
||||
let verts = vec![Vertex::default(); num_quads * VERTICES_PER_CELL];
|
||||
let mut indices = vec![];
|
||||
indices.reserve(num_quads * INDICES_PER_CELL);
|
||||
@ -319,7 +300,7 @@ impl RenderState {
|
||||
VertexBuffer::dynamic(context, &verts)?,
|
||||
VertexBuffer::dynamic(context, &verts)?,
|
||||
]),
|
||||
capacity: verts.len() / VERTICES_PER_CELL,
|
||||
capacity: num_quads,
|
||||
indices: IndexBuffer::new(
|
||||
context,
|
||||
glium::index::PrimitiveType::TrianglesList,
|
||||
|
@ -298,14 +298,7 @@ impl TermWindow {
|
||||
) -> anyhow::Result<()> {
|
||||
self.render_state = None;
|
||||
|
||||
match RenderState::new(
|
||||
ctx,
|
||||
&self.fonts,
|
||||
&self.render_metrics,
|
||||
ATLAS_SIZE,
|
||||
self.dimensions.pixel_width,
|
||||
self.dimensions.pixel_height,
|
||||
) {
|
||||
match RenderState::new(ctx, &self.fonts, &self.render_metrics, ATLAS_SIZE) {
|
||||
Ok(gl) => {
|
||||
log::info!(
|
||||
"OpenGL initialized! {} {} is_context_loss_possible={} wezterm version: {}",
|
||||
|
@ -99,7 +99,27 @@ impl super::TermWindow {
|
||||
|
||||
for pass in 0.. {
|
||||
match self.paint_opengl_pass() {
|
||||
Ok(_) => break,
|
||||
Ok(_) => {
|
||||
let gl_state = self.render_state.as_mut().unwrap();
|
||||
if let Some(need_quads) = gl_state.glyph_vertex_buffer.need_more_quads() {
|
||||
// Round up to next multiple of 1024 that is >=
|
||||
// the number of needed quads for this frame
|
||||
let num_quads = (need_quads + 1023) & !1023;
|
||||
if let Err(err) = gl_state.reallocate_quads(num_quads) {
|
||||
log::error!(
|
||||
"Failed to allocate {} quads (needed {}): {:#}",
|
||||
num_quads,
|
||||
need_quads,
|
||||
err
|
||||
);
|
||||
break;
|
||||
}
|
||||
log::trace!("Allocated {} quads (needed {})", num_quads, need_quads);
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
Err(err) => {
|
||||
if let Some(&OutOfTextureSpace {
|
||||
size: Some(size),
|
||||
|
@ -74,10 +74,8 @@ impl super::TermWindow {
|
||||
pub fn apply_dimensions(
|
||||
&mut self,
|
||||
dimensions: &Dimensions,
|
||||
mut scale_changed_cells: Option<RowsAndCols>,
|
||||
scale_changed_cells: Option<RowsAndCols>,
|
||||
) {
|
||||
let orig_dimensions = self.dimensions;
|
||||
|
||||
self.dimensions = *dimensions;
|
||||
|
||||
// Technically speaking, we should compute the rows and cols
|
||||
@ -143,25 +141,8 @@ impl super::TermWindow {
|
||||
(size, *dimensions)
|
||||
};
|
||||
|
||||
if let Some(render_state) = self.render_state.as_mut() {
|
||||
if let Err(err) = render_state.advise_of_window_size_change(
|
||||
&self.render_metrics,
|
||||
dimensions.pixel_width,
|
||||
dimensions.pixel_height,
|
||||
) {
|
||||
log::error!(
|
||||
"failed to advise of resize from {:?} -> {:?}: {:?}",
|
||||
orig_dimensions,
|
||||
dimensions,
|
||||
err
|
||||
);
|
||||
// Try to restore the original dimensions
|
||||
self.dimensions = orig_dimensions;
|
||||
// Avoid the inner resize below
|
||||
scale_changed_cells.take();
|
||||
} else {
|
||||
self.terminal_size = size;
|
||||
}
|
||||
if self.render_state.is_some() {
|
||||
self.terminal_size = size;
|
||||
}
|
||||
|
||||
let mux = Mux::get().unwrap();
|
||||
|
Loading…
Reference in New Issue
Block a user