From 0458d9a7f28bb786043ff577bc937fed1b34199b Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 18 Mar 2019 21:40:10 -0700 Subject: [PATCH] Factor out bits of the postprocessing shader into includes --- Cargo.lock | 1 + gl/src/lib.rs | 11 +++++- gpu/Cargo.toml | 1 + gpu/src/lib.rs | 28 ++++++++++--- gpu/src/resources.rs | 7 +--- renderer/src/gpu/renderer.rs | 2 - resources/shaders/post.fs.glsl | 39 ++----------------- resources/shaders/post_convolve.inc.glsl | 37 ++++++++++++++++++ resources/shaders/post_gamma_correct.inc.glsl | 28 +++++++++++++ 9 files changed, 103 insertions(+), 51 deletions(-) create mode 100644 resources/shaders/post_convolve.inc.glsl create mode 100644 resources/shaders/post_gamma_correct.inc.glsl diff --git a/Cargo.lock b/Cargo.lock index d71e7e72..79cc8730 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -691,6 +691,7 @@ dependencies = [ "image 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", "pathfinder_geometry 0.3.0", "pathfinder_simd 0.3.0", + "rustache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/gl/src/lib.rs b/gl/src/lib.rs index cf6e1620..030224be 100644 --- a/gl/src/lib.rs +++ b/gl/src/lib.rs @@ -209,9 +209,16 @@ impl Device for GLDevice { texture } - fn create_shader_from_source(&self, name: &str, source: &[u8], kind: ShaderKind) -> GLShader { + fn create_shader_from_source(&self, + name: &str, + source: &[u8], + kind: ShaderKind, + mut template_input: HashBuilder) + -> GLShader { + // FIXME(pcwalton): Do this once and cache it. let glsl_version_spec = self.version.to_glsl_version_spec(); - let template_input = HashBuilder::new().insert("version", glsl_version_spec); + template_input = template_input.insert("version", glsl_version_spec); + let mut output = Cursor::new(vec![]); template_input.render(str::from_utf8(source).unwrap(), &mut output).unwrap(); let source = output.into_inner(); diff --git a/gpu/Cargo.toml b/gpu/Cargo.toml index c493efa2..e57a847f 100644 --- a/gpu/Cargo.toml +++ b/gpu/Cargo.toml @@ -5,6 +5,7 @@ authors = ["Patrick Walton "] edition = "2018" [dependencies] +rustache = "0.1" [dependencies.image] version = "0.21" diff --git a/gpu/src/lib.rs b/gpu/src/lib.rs index e0f7793e..f8b3c91b 100644 --- a/gpu/src/lib.rs +++ b/gpu/src/lib.rs @@ -15,10 +15,7 @@ use image::ImageFormat; use pathfinder_geometry::basic::point::Point2DI32; use pathfinder_geometry::basic::rect::RectI32; use pathfinder_simd::default::F32x4; -use std::env; -use std::fs::File; -use std::io::Read; -use std::path::PathBuf; +use rustache::HashBuilder; use std::time::Duration; pub mod resources; @@ -36,7 +33,11 @@ pub trait Device { fn create_texture(&self, format: TextureFormat, size: Point2DI32) -> Self::Texture; fn create_texture_from_data(&self, size: Point2DI32, data: &[u8]) -> Self::Texture; - fn create_shader_from_source(&self, name: &str, source: &[u8], kind: ShaderKind) + fn create_shader_from_source(&self, + name: &str, + source: &[u8], + kind: ShaderKind, + template_input: HashBuilder) -> Self::Shader; fn create_vertex_array(&self) -> Self::VertexArray; fn create_program_from_shaders(&self, @@ -108,7 +109,17 @@ pub trait Device { -> Self::Shader { let suffix = match kind { ShaderKind::Vertex => 'v', ShaderKind::Fragment => 'f' }; let source = resources.slurp(&format!("shaders/{}.{}s.glsl", name, suffix)).unwrap(); - self.create_shader_from_source(name, &source, kind) + + let mut load_include_post_convolve = |_| load_shader_include(resources, "post_convolve"); + let mut load_include_post_gamma_correct = + |_| load_shader_include(resources, "post_gamma_correct"); + let template_input = + HashBuilder::new().insert_lambda("include_post_convolve", + &mut load_include_post_convolve) + .insert_lambda("include_post_gamma_correct", + &mut load_include_post_gamma_correct); + + self.create_shader_from_source(name, &source, kind, template_input) } fn create_program(&self, resources: &dyn ResourceLoader, name: &str) -> Self::Program { @@ -242,3 +253,8 @@ impl Default for StencilFunc { StencilFunc::Always } } + +fn load_shader_include(resources: &dyn ResourceLoader, include_name: &str) -> String { + let resource = resources.slurp(&format!("shaders/{}.inc.glsl", include_name)).unwrap(); + String::from_utf8_lossy(&resource).to_string() +} diff --git a/gpu/src/resources.rs b/gpu/src/resources.rs index fe7ceb29..63638a30 100644 --- a/gpu/src/resources.rs +++ b/gpu/src/resources.rs @@ -12,7 +12,6 @@ //! //! We can't always count on a filesystem being present. -use crate::ShaderKind; use std::env; use std::fs::File; use std::io::{Error as IOError, Read}; @@ -29,7 +28,7 @@ pub struct FilesystemResourceLoader { } impl FilesystemResourceLoader { - pub fn new(root: PathBuf) -> FilesystemResourceLoader { + pub fn locate() -> FilesystemResourceLoader { let mut parent_directory = env::current_dir().unwrap(); loop { // So ugly :( @@ -52,10 +51,6 @@ impl FilesystemResourceLoader { panic!("No suitable `resources/` directory found!"); } - - pub fn locate() -> FilesystemResourceLoader { - FilesystemResourceLoader::new(env::current_dir().unwrap()) - } } impl ResourceLoader for FilesystemResourceLoader { diff --git a/renderer/src/gpu/renderer.rs b/renderer/src/gpu/renderer.rs index bb4a22be..6a54e184 100644 --- a/renderer/src/gpu/renderer.rs +++ b/renderer/src/gpu/renderer.rs @@ -70,7 +70,6 @@ pub struct Renderer where D: Device { // Extra info viewport: RectI32, - main_framebuffer_size: Point2DI32, postprocess_options: PostprocessOptions, use_depth: bool, } @@ -150,7 +149,6 @@ impl Renderer where D: Device { debug_ui, viewport, - main_framebuffer_size, postprocess_options: PostprocessOptions::default(), use_depth: false, } diff --git a/resources/shaders/post.fs.glsl b/resources/shaders/post.fs.glsl index d645c1d0..9915b403 100644 --- a/resources/shaders/post.fs.glsl +++ b/resources/shaders/post.fs.glsl @@ -1,6 +1,6 @@ #version {{version}} -// pathfinder/demo/shaders/post.fs.glsl +// pathfinder/resources/shaders/post.fs.glsl // // Copyright © 2019 The Pathfinder Project Developers. // @@ -16,51 +16,20 @@ precision highp float; uniform sampler2D uSource; -uniform sampler2D uGammaLUT; uniform vec2 uFramebufferSize; -// Zero if no subpixel AA is to be performed. -uniform vec4 uKernel; -// Zero if no gamma correction is to be performed. -uniform vec4 uGammaCorrectionBGColor; in vec2 vTexCoord; out vec4 oFragColor; -float gammaCorrectChannel(float fgColor) { - return texture(uGammaLUT, vec2(fgColor, 1.0 - uGammaCorrectionBGColor)).r; -} - -// `fgColor` is in linear space. -vec3 gammaCorrect(vec3 fgColor) { - return vec3(gammaCorrectChannel(fgColor.r), - gammaCorrectChannel(fgColor.g), - gammaCorrectChannel(fgColor.b)); -} +{{{include_post_gamma_correct}}} +{{{include_post_convolve}}} +// Convolve horizontally in this pass. float sample1Tap(float offset) { return texture(uSource, vec2(vTexCoord.x + offset, vTexCoord.y)).r; } -void sample9Tap(out vec4 outAlphaLeft, - out float outAlphaCenter, - out vec4 outAlphaRight, - float onePixel) { - outAlphaLeft = vec4(uKernel.x > 0.0 ? sample1Tap(-4.0 * onePixel) : 0.0, - sample1Tap(-3.0 * onePixel), - sample1Tap(-2.0 * onePixel), - sample1Tap(-1.0 * onePixel)); - outAlphaCenter = sample1Tap(0.0); - outAlphaRight = vec4(sample1Tap(1.0 * onePixel), - sample1Tap(2.0 * onePixel), - sample1Tap(3.0 * onePixel), - uKernel.x > 0.0 ? sample1Tap(4.0 * onePixel) : 0.0); -} - -float convolve7Tap(vec4 alpha0, vec3 alpha1) { - return dot(alpha0, uKernel) + dot(alpha1, uKernel.zyx); -} - void main() { // Apply defringing if necessary. vec4 fgColor = texture(uSource, vTexCoord); diff --git a/resources/shaders/post_convolve.inc.glsl b/resources/shaders/post_convolve.inc.glsl new file mode 100644 index 00000000..8eab750b --- /dev/null +++ b/resources/shaders/post_convolve.inc.glsl @@ -0,0 +1,37 @@ +// pathfinder/resources/shaders/post_convolve.inc.glsl +// +// Copyright © 2019 The Pathfinder Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Zero if no convolution is to be performed. +uniform vec4 uKernel; + +// This function is expected to return the alpha value of the pixel at the +// given offset in pixels. Offset 0.0 represents the current pixel. +float sample1Tap(float offset); + +// Samples 9 taps around the current pixel. +void sample9Tap(out vec4 outAlphaLeft, + out float outAlphaCenter, + out vec4 outAlphaRight, + float onePixel) { + outAlphaLeft = vec4(uKernel.x > 0.0 ? sample1Tap(-4.0 * onePixel) : 0.0, + sample1Tap(-3.0 * onePixel), + sample1Tap(-2.0 * onePixel), + sample1Tap(-1.0 * onePixel)); + outAlphaCenter = sample1Tap(0.0); + outAlphaRight = vec4(sample1Tap(1.0 * onePixel), + sample1Tap(2.0 * onePixel), + sample1Tap(3.0 * onePixel), + uKernel.x > 0.0 ? sample1Tap(4.0 * onePixel) : 0.0); +} + +// Convolves 7 values with the kernel. +float convolve7Tap(vec4 alpha0, vec3 alpha1) { + return dot(alpha0, uKernel) + dot(alpha1, uKernel.zyx); +} diff --git a/resources/shaders/post_gamma_correct.inc.glsl b/resources/shaders/post_gamma_correct.inc.glsl new file mode 100644 index 00000000..df25d250 --- /dev/null +++ b/resources/shaders/post_gamma_correct.inc.glsl @@ -0,0 +1,28 @@ +// pathfinder/resources/shaders/post_gamma_correct.inc.glsl +// +// Copyright © 2019 The Pathfinder Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// The lookup table for gamma correction, in the same format WebRender +// expects. +uniform sampler2D uGammaLUT; + +// The background color to blend against. Zero if no gamma correction is to be +// performed. +uniform vec4 uGammaCorrectionBGColor; + +float gammaCorrectChannel(float fgColor) { + return texture(uGammaLUT, vec2(fgColor, 1.0 - uGammaCorrectionBGColor)).r; +} + +// `fgColor` is in linear space. +vec3 gammaCorrect(vec3 fgColor) { + return vec3(gammaCorrectChannel(fgColor.r), + gammaCorrectChannel(fgColor.g), + gammaCorrectChannel(fgColor.b)); +}