mirror of
https://github.com/wez/wezterm.git
synced 2024-12-25 14:22:37 +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> {
|
impl<'a> MappedQuads<'a> {
|
||||||
pub fn allocate<'b>(&'b mut self) -> anyhow::Result<Quad<'b>> {
|
pub fn allocate<'b>(&'b mut self) -> anyhow::Result<Quad<'b>> {
|
||||||
let idx = *self.next;
|
let idx = *self.next;
|
||||||
if idx >= self.capacity {
|
|
||||||
anyhow::bail!("not enough quads! do something like OutOfTextureSpace");
|
|
||||||
}
|
|
||||||
*self.next += 1;
|
*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 idx = idx * VERTICES_PER_CELL;
|
||||||
let mut quad = Quad {
|
let mut quad = Quad {
|
||||||
@ -52,6 +58,15 @@ impl TripleVertexBuffer {
|
|||||||
*self.next_quad.borrow_mut() = 0;
|
*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) {
|
pub fn vertex_index_count(&self) -> (usize, usize) {
|
||||||
let num_quads = *self.next_quad.borrow();
|
let num_quads = *self.next_quad.borrow();
|
||||||
(num_quads * VERTICES_PER_CELL, num_quads * INDICES_PER_CELL)
|
(num_quads * VERTICES_PER_CELL, num_quads * INDICES_PER_CELL)
|
||||||
@ -104,8 +119,6 @@ impl RenderState {
|
|||||||
fonts: &Rc<FontConfiguration>,
|
fonts: &Rc<FontConfiguration>,
|
||||||
metrics: &RenderMetrics,
|
metrics: &RenderMetrics,
|
||||||
mut atlas_size: usize,
|
mut atlas_size: usize,
|
||||||
pixel_width: usize,
|
|
||||||
pixel_height: usize,
|
|
||||||
) -> anyhow::Result<Self> {
|
) -> anyhow::Result<Self> {
|
||||||
loop {
|
loop {
|
||||||
let glyph_cache =
|
let glyph_cache =
|
||||||
@ -123,12 +136,7 @@ impl RenderState {
|
|||||||
// Last prog outputs srgb for gamma correction
|
// Last prog outputs srgb for gamma correction
|
||||||
let img_prog = Self::compile_prog(&context, true, Self::img_shader)?;
|
let img_prog = Self::compile_prog(&context, true, Self::img_shader)?;
|
||||||
|
|
||||||
let glyph_vertex_buffer = Self::compute_vertices(
|
let glyph_vertex_buffer = Self::compute_vertices(&context, 1024)?;
|
||||||
&context,
|
|
||||||
metrics,
|
|
||||||
pixel_width as f32,
|
|
||||||
pixel_height as f32,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
return Ok(Self {
|
return Ok(Self {
|
||||||
context,
|
context,
|
||||||
@ -183,18 +191,8 @@ impl RenderState {
|
|||||||
anyhow::bail!("Failed to compile shaders: {}", errors.join("\n"))
|
anyhow::bail!("Failed to compile shaders: {}", errors.join("\n"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn advise_of_window_size_change(
|
pub fn reallocate_quads(&mut self, num_quads: usize) -> anyhow::Result<()> {
|
||||||
&mut self,
|
let glyph_vertex_buffer = Self::compute_vertices(&self.context, num_quads)?;
|
||||||
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,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
self.glyph_vertex_buffer = glyph_vertex_buffer;
|
self.glyph_vertex_buffer = glyph_vertex_buffer;
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -276,25 +274,8 @@ impl RenderState {
|
|||||||
/// let the GPU figure out the rest.
|
/// let the GPU figure out the rest.
|
||||||
fn compute_vertices(
|
fn compute_vertices(
|
||||||
context: &Rc<GliumContext>,
|
context: &Rc<GliumContext>,
|
||||||
metrics: &RenderMetrics,
|
num_quads: usize,
|
||||||
width: f32,
|
|
||||||
height: f32,
|
|
||||||
) -> anyhow::Result<TripleVertexBuffer> {
|
) -> 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 verts = vec![Vertex::default(); num_quads * VERTICES_PER_CELL];
|
||||||
let mut indices = vec![];
|
let mut indices = vec![];
|
||||||
indices.reserve(num_quads * INDICES_PER_CELL);
|
indices.reserve(num_quads * INDICES_PER_CELL);
|
||||||
@ -319,7 +300,7 @@ impl RenderState {
|
|||||||
VertexBuffer::dynamic(context, &verts)?,
|
VertexBuffer::dynamic(context, &verts)?,
|
||||||
VertexBuffer::dynamic(context, &verts)?,
|
VertexBuffer::dynamic(context, &verts)?,
|
||||||
]),
|
]),
|
||||||
capacity: verts.len() / VERTICES_PER_CELL,
|
capacity: num_quads,
|
||||||
indices: IndexBuffer::new(
|
indices: IndexBuffer::new(
|
||||||
context,
|
context,
|
||||||
glium::index::PrimitiveType::TrianglesList,
|
glium::index::PrimitiveType::TrianglesList,
|
||||||
|
@ -298,14 +298,7 @@ impl TermWindow {
|
|||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
self.render_state = None;
|
self.render_state = None;
|
||||||
|
|
||||||
match RenderState::new(
|
match RenderState::new(ctx, &self.fonts, &self.render_metrics, ATLAS_SIZE) {
|
||||||
ctx,
|
|
||||||
&self.fonts,
|
|
||||||
&self.render_metrics,
|
|
||||||
ATLAS_SIZE,
|
|
||||||
self.dimensions.pixel_width,
|
|
||||||
self.dimensions.pixel_height,
|
|
||||||
) {
|
|
||||||
Ok(gl) => {
|
Ok(gl) => {
|
||||||
log::info!(
|
log::info!(
|
||||||
"OpenGL initialized! {} {} is_context_loss_possible={} wezterm version: {}",
|
"OpenGL initialized! {} {} is_context_loss_possible={} wezterm version: {}",
|
||||||
|
@ -99,7 +99,27 @@ impl super::TermWindow {
|
|||||||
|
|
||||||
for pass in 0.. {
|
for pass in 0.. {
|
||||||
match self.paint_opengl_pass() {
|
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) => {
|
Err(err) => {
|
||||||
if let Some(&OutOfTextureSpace {
|
if let Some(&OutOfTextureSpace {
|
||||||
size: Some(size),
|
size: Some(size),
|
||||||
|
@ -74,10 +74,8 @@ impl super::TermWindow {
|
|||||||
pub fn apply_dimensions(
|
pub fn apply_dimensions(
|
||||||
&mut self,
|
&mut self,
|
||||||
dimensions: &Dimensions,
|
dimensions: &Dimensions,
|
||||||
mut scale_changed_cells: Option<RowsAndCols>,
|
scale_changed_cells: Option<RowsAndCols>,
|
||||||
) {
|
) {
|
||||||
let orig_dimensions = self.dimensions;
|
|
||||||
|
|
||||||
self.dimensions = *dimensions;
|
self.dimensions = *dimensions;
|
||||||
|
|
||||||
// Technically speaking, we should compute the rows and cols
|
// Technically speaking, we should compute the rows and cols
|
||||||
@ -143,25 +141,8 @@ impl super::TermWindow {
|
|||||||
(size, *dimensions)
|
(size, *dimensions)
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(render_state) = self.render_state.as_mut() {
|
if self.render_state.is_some() {
|
||||||
if let Err(err) = render_state.advise_of_window_size_change(
|
self.terminal_size = size;
|
||||||
&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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mux = Mux::get().unwrap();
|
let mux = Mux::get().unwrap();
|
||||||
|
Loading…
Reference in New Issue
Block a user