Skip to content

Commit

Permalink
reduce to a single draw call
Browse files Browse the repository at this point in the history
Taking further advantage of dynamic quad allocation, we can now
remove the multiple render passes in favor of allocating the quads
and painting them from back to front.

In turn, this means that we can reduce the amount of data that we
store in the vertex, which simplifies the shaders a bit, at the
expense of making the render code in rust a bit more complex.

However, we can take advantage of stretching runs of cells with
background colors in to a single quad.

refs: #986
  • Loading branch information
wez committed Jul 31, 2021
1 parent 9a8b2e1 commit 725572d
Show file tree
Hide file tree
Showing 13 changed files with 251 additions and 480 deletions.
6 changes: 4 additions & 2 deletions color-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ impl SrgbaPixel {
}

/// A pixel value encoded as linear RGBA values in f32 format (range: 0.0-1.0)
#[derive(Copy, Clone, Debug, Default)]
#[derive(Copy, Clone, Debug, Default, PartialEq)]
pub struct LinearRgba(f32, f32, f32, f32);

impl LinearRgba {
Expand All @@ -232,10 +232,12 @@ impl LinearRgba {
}

/// Create using the provided f32 components in the range 0.0-1.0
pub fn with_components(red: f32, green: f32, blue: f32, alpha: f32) -> Self {
pub const fn with_components(red: f32, green: f32, blue: f32, alpha: f32) -> Self {
Self(red, green, blue, alpha)
}

pub const TRANSPARENT: Self = Self::with_components(0., 0., 0., 0.);

/// Convert to an SRGB u32 pixel
pub fn srgba_pixel(self) -> SrgbaPixel {
SrgbaPixel::rgba(
Expand Down
20 changes: 0 additions & 20 deletions wezterm-gui/src/background-frag.glsl

This file was deleted.

16 changes: 0 additions & 16 deletions wezterm-gui/src/background-vertex.glsl

This file was deleted.

14 changes: 9 additions & 5 deletions wezterm-gui/src/fragment-common.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,9 @@
precision highp float;

in float o_has_color;
in vec2 o_cursor;
in vec2 o_tex;
in vec2 o_underline;
in vec3 o_hsv;
in vec4 o_bg_color;
in vec4 o_cursor_color;
in vec4 o_fg_color;
in vec4 o_underline_color;

out vec4 color;

Expand Down Expand Up @@ -88,6 +83,15 @@ vec4 colorize(vec4 glyph, vec4 color, vec4 background) {
// return vec4(glyph.rgb * color.rgb, glyph.a);
}

vec4 colorize2(vec4 glyph, vec4 color) {
float r = glyph.r * color.r;// + (1.0 - glyph.r) * background.r;
float g = glyph.g * color.g;// + (1.0 - glyph.g) * background.g;
float b = glyph.b * color.b;// + (1.0 - glyph.b) * background.b;

return vec4(r, g, b, glyph.a);
// return vec4(glyph.rgb * color.rgb, glyph.a);
}

vec4 from_linear(vec4 v) {
return pow(v, vec4(2.2));
}
Expand Down
33 changes: 12 additions & 21 deletions wezterm-gui/src/glyph-frag.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,20 @@
// Note: fragment-common.glsl is automatically prepended!

uniform sampler2D atlas_nearest_sampler;
uniform sampler2D atlas_linear_sampler;

void main() {
if (o_has_color >= 2.0) {
// Don't render the background image on anything other than
// the window_bg_layer.
discard;
return;
}

color = sample_texture(atlas_nearest_sampler, o_tex);
if (o_has_color == 0.0) {
// if it's not a color emoji it will be grayscale
// and we need to tint with the fg_color
if (o_fg_color == o_bg_color) {
// However, if we're a monochrome glyph and the foreground and
// background colors are the same, just render a transparent pixel
// instead; this avoids generating shadowy anti-aliasing artifacts
// for something that should otherwise be invisible.
color = vec4(0.0, 0.0, 0.0, 0.0);
discard;
return;
} else {
color = colorize(color, o_fg_color, o_bg_color);
if (o_has_color == 2.0) {
// The window background attachment
color = sample_texture(atlas_linear_sampler, o_tex);
// Apply window_background_image_opacity to the background image
color.a = o_fg_color.a;
} else {
color = sample_texture(atlas_nearest_sampler, o_tex);
if (o_has_color == 0.0) {
// if it's not a color emoji it will be grayscale
// and we need to tint with the fg_color
color = colorize2(color, o_fg_color);
color = apply_hsv(color, foreground_text_hsb);
}
}
Expand Down
10 changes: 2 additions & 8 deletions wezterm-gui/src/glyph-vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,6 @@
void main() {
pass_through_vertex();

if (o_has_color == 2.0) {
// If we're the background image and we're not rendering
// the background layer, then move this off screen
gl_Position = off_screen();
} else {
// Use only the adjusted cell position to render the glyph
gl_Position = projection * vec4(position + adjust, 0.0, 1.0);
}
// Use only the adjusted cell position to render the glyph
gl_Position = projection * vec4(position + adjust, 0.0, 1.0);
}
41 changes: 0 additions & 41 deletions wezterm-gui/src/line-frag.glsl

This file was deleted.

17 changes: 0 additions & 17 deletions wezterm-gui/src/line-vertex.glsl

This file was deleted.

55 changes: 1 addition & 54 deletions wezterm-gui/src/quad.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,7 @@ pub struct Vertex {
pub adjust: (f32, f32),
// glyph texture
pub tex: (f32, f32),
// underline texture
pub underline: (f32, f32),
// cursor texture
pub cursor: (f32, f32),
pub cursor_color: (f32, f32, f32, f32),
pub bg_color: (f32, f32, f32, f32),
pub fg_color: (f32, f32, f32, f32),
pub underline_color: (f32, f32, f32, f32),
pub hsv: (f32, f32, f32),
// We use a float for this because I can't get
// bool or integer values to work:
Expand All @@ -44,20 +37,7 @@ pub struct Vertex {
// image, we use the solid bg color
pub has_color: f32,
}
::window::glium::implement_vertex!(
Vertex,
position,
adjust,
tex,
underline,
cursor,
cursor_color,
bg_color,
fg_color,
underline_color,
hsv,
has_color
);
::window::glium::implement_vertex!(Vertex, position, adjust, tex, fg_color, hsv, has_color);

/// A helper for updating the 4 vertices that compose a glyph cell
pub struct Quad<'a> {
Expand Down Expand Up @@ -109,39 +89,6 @@ impl<'a> Quad<'a> {
}
}

pub fn set_underline_color(&mut self, color: LinearRgba) {
for v in self.vert.iter_mut() {
v.underline_color = color.tuple();
}
}

pub fn set_bg_color(&mut self, color: LinearRgba) {
for v in self.vert.iter_mut() {
v.bg_color = color.tuple();
}
}

/// Assign the underline texture coordinates for the cell
pub fn set_underline(&mut self, coords: TextureRect) {
self.vert[V_TOP_LEFT].underline = (coords.min_x(), coords.min_y());
self.vert[V_TOP_RIGHT].underline = (coords.max_x(), coords.min_y());
self.vert[V_BOT_LEFT].underline = (coords.min_x(), coords.max_y());
self.vert[V_BOT_RIGHT].underline = (coords.max_x(), coords.max_y());
}

pub fn set_cursor(&mut self, coords: TextureRect) {
self.vert[V_TOP_LEFT].cursor = (coords.min_x(), coords.min_y());
self.vert[V_TOP_RIGHT].cursor = (coords.max_x(), coords.min_y());
self.vert[V_BOT_LEFT].cursor = (coords.min_x(), coords.max_y());
self.vert[V_BOT_RIGHT].cursor = (coords.max_x(), coords.max_y());
}

pub fn set_cursor_color(&mut self, color: LinearRgba) {
for v in self.vert.iter_mut() {
v.cursor_color = color.tuple();
}
}

pub fn set_hsv(&mut self, hsv: Option<config::HsbTransform>) {
let s = hsv
.map(|t| (t.hue, t.saturation, t.brightness))
Expand Down
44 changes: 0 additions & 44 deletions wezterm-gui/src/renderstate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,6 @@ pub struct RenderState {
pub context: Rc<GliumContext>,
pub glyph_cache: RefCell<GlyphCache<SrgbTexture2d>>,
pub util_sprites: UtilSprites<SrgbTexture2d>,
pub background_prog: glium::Program,
pub line_prog: glium::Program,
pub glyph_prog: glium::Program,
pub glyph_vertex_buffer: TripleVertexBuffer,
}
Expand All @@ -125,12 +123,6 @@ impl RenderState {
let result = UtilSprites::new(&mut *glyph_cache.borrow_mut(), metrics);
match result {
Ok(util_sprites) => {
let do_gamma = cfg!(target_os = "macos");

let background_prog =
Self::compile_prog(&context, do_gamma, Self::background_shader)?;
let line_prog = Self::compile_prog(&context, do_gamma, Self::line_shader)?;

// Last prog outputs srgb for gamma correction
let glyph_prog = Self::compile_prog(&context, true, Self::glyph_shader)?;

Expand All @@ -140,8 +132,6 @@ impl RenderState {
context,
glyph_cache,
util_sprites,
background_prog,
line_prog,
glyph_prog,
glyph_vertex_buffer,
});
Expand Down Expand Up @@ -212,40 +202,6 @@ impl RenderState {
)
}

fn line_shader(version: &str) -> (String, String) {
(
format!(
"#version {}\n{}\n{}",
version,
include_str!("vertex-common.glsl"),
include_str!("line-vertex.glsl")
),
format!(
"#version {}\n{}\n{}",
version,
include_str!("fragment-common.glsl"),
include_str!("line-frag.glsl")
),
)
}

fn background_shader(version: &str) -> (String, String) {
(
format!(
"#version {}\n{}\n{}",
version,
include_str!("vertex-common.glsl"),
include_str!("background-vertex.glsl")
),
format!(
"#version {}\n{}\n{}",
version,
include_str!("fragment-common.glsl"),
include_str!("background-frag.glsl")
),
)
}

/// Compute a vertex buffer to hold the quads that comprise the visible
/// portion of the screen. We recreate this when the screen is resized.
/// The idea is that we want to minimize any heavy lifting and computation
Expand Down
Loading

0 comments on commit 725572d

Please sign in to comment.