1
1
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:
Wez Furlong 2021-07-30 16:59:47 -07:00
parent 6a84f051b6
commit 89586d658e
4 changed files with 48 additions and 73 deletions

View File

@ -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,

View File

@ -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: {}",

View File

@ -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),

View File

@ -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();