Improve error handling for shader initialization

Shader initialization errors at startup should print a nice message now.
This commit is contained in:
Joe Wilm 2017-01-01 19:19:15 -08:00
parent d4e20a4741
commit 7c794ada88
2 changed files with 57 additions and 9 deletions

View File

@ -24,7 +24,7 @@ use cli;
use config::Config; use config::Config;
use font::{self, Rasterize}; use font::{self, Rasterize};
use meter::Meter; use meter::Meter;
use renderer::{GlyphCache, QuadRenderer}; use renderer::{self, GlyphCache, QuadRenderer};
use selection::Selection; use selection::Selection;
use term::{Term, SizeInfo}; use term::{Term, SizeInfo};
@ -37,6 +37,9 @@ pub enum Error {
/// Error dealing with fonts /// Error dealing with fonts
Font(font::Error), Font(font::Error),
/// Error in renderer
Render(renderer::Error),
} }
impl ::std::error::Error for Error { impl ::std::error::Error for Error {
@ -44,6 +47,7 @@ impl ::std::error::Error for Error {
match *self { match *self {
Error::Window(ref err) => Some(err), Error::Window(ref err) => Some(err),
Error::Font(ref err) => Some(err), Error::Font(ref err) => Some(err),
Error::Render(ref err) => Some(err),
} }
} }
@ -51,6 +55,7 @@ impl ::std::error::Error for Error {
match *self { match *self {
Error::Window(ref err) => err.description(), Error::Window(ref err) => err.description(),
Error::Font(ref err) => err.description(), Error::Font(ref err) => err.description(),
Error::Render(ref err) => err.description(),
} }
} }
} }
@ -60,6 +65,7 @@ impl ::std::fmt::Display for Error {
match *self { match *self {
Error::Window(ref err) => err.fmt(f), Error::Window(ref err) => err.fmt(f),
Error::Font(ref err) => err.fmt(f), Error::Font(ref err) => err.fmt(f),
Error::Render(ref err) => err.fmt(f),
} }
} }
} }
@ -76,6 +82,12 @@ impl From<font::Error> for Error {
} }
} }
impl From<renderer::Error> for Error {
fn from(val: renderer::Error) -> Error {
Error::Render(val)
}
}
/// The display wraps a window, font rasterizer, and GPU renderer /// The display wraps a window, font rasterizer, and GPU renderer
pub struct Display { pub struct Display {
window: Window, window: Window,
@ -139,7 +151,7 @@ impl Display {
let rasterizer = font::Rasterizer::new(dpi.x(), dpi.y(), dpr)?; let rasterizer = font::Rasterizer::new(dpi.x(), dpi.y(), dpr)?;
// Create renderer // Create renderer
let mut renderer = QuadRenderer::new(config, size); let mut renderer = QuadRenderer::new(config, size)?;
// Initialize glyph cache // Initialize glyph cache
let glyph_cache = { let glyph_cache = {

View File

@ -57,6 +57,42 @@ enum Msg {
ShaderReload, ShaderReload,
} }
#[derive(Debug)]
pub enum Error {
ShaderCreation(ShaderCreationError),
}
impl ::std::error::Error for Error {
fn cause(&self) -> Option<&::std::error::Error> {
match *self {
Error::ShaderCreation(ref err) => Some(err),
}
}
fn description(&self) -> &str {
match *self {
Error::ShaderCreation(ref err) => err.description(),
}
}
}
impl ::std::fmt::Display for Error {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
match *self {
Error::ShaderCreation(ref err) => {
write!(f, "There was an error initializing the shaders: {}", err)
}
}
}
}
impl From<ShaderCreationError> for Error {
fn from(val: ShaderCreationError) -> Error {
Error::ShaderCreation(val)
}
}
/// Text drawing program /// Text drawing program
/// ///
/// Uniforms are prefixed with "u", and vertex attributes are prefixed with "a". /// Uniforms are prefixed with "u", and vertex attributes are prefixed with "a".
@ -395,8 +431,8 @@ const ATLAS_SIZE: i32 = 1024;
impl QuadRenderer { impl QuadRenderer {
// TODO should probably hand this a transform instead of width/height // TODO should probably hand this a transform instead of width/height
pub fn new(config: &Config, size: Size<Pixels<u32>>) -> QuadRenderer { pub fn new(config: &Config, size: Size<Pixels<u32>>) -> Result<QuadRenderer, Error> {
let program = ShaderProgram::new(size).unwrap(); let program = ShaderProgram::new(size)?;
let mut vao: GLuint = 0; let mut vao: GLuint = 0;
let mut vbo: GLuint = 0; let mut vbo: GLuint = 0;
@ -503,7 +539,7 @@ impl QuadRenderer {
if cfg!(feature = "live-shader-reload") { if cfg!(feature = "live-shader-reload") {
::std::thread::spawn(move || { ::std::thread::spawn(move || {
let (tx, rx) = ::std::sync::mpsc::channel(); let (tx, rx) = ::std::sync::mpsc::channel();
let mut watcher = Watcher::new(tx).unwrap(); let mut watcher = Watcher::new(tx).expect("create file watcher");
watcher.watch(TEXT_SHADER_F_PATH).expect("watch fragment shader"); watcher.watch(TEXT_SHADER_F_PATH).expect("watch fragment shader");
watcher.watch(TEXT_SHADER_V_PATH).expect("watch vertex shader"); watcher.watch(TEXT_SHADER_V_PATH).expect("watch vertex shader");
@ -547,7 +583,7 @@ impl QuadRenderer {
let atlas = Atlas::new(ATLAS_SIZE); let atlas = Atlas::new(ATLAS_SIZE);
renderer.atlas.push(atlas); renderer.atlas.push(atlas);
renderer Ok(renderer)
} }
pub fn update_config(&mut self, config: &Config) { pub fn update_config(&mut self, config: &Config) {
@ -625,7 +661,7 @@ impl QuadRenderer {
}, },
ShaderCreationError::Compile(path, log) => { ShaderCreationError::Compile(path, log) => {
err_println!("Error compiling shader at {:?}", path); err_println!("Error compiling shader at {:?}", path);
io::copy(&mut log.as_bytes(), &mut io::stdout()).unwrap(); let _ = io::copy(&mut log.as_bytes(), &mut io::stdout());
} }
} }
@ -1094,9 +1130,9 @@ impl ::std::error::Error for ShaderCreationError {
impl ::std::fmt::Display for ShaderCreationError { impl ::std::fmt::Display for ShaderCreationError {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
match *self { match *self {
ShaderCreationError::Io(ref err) => write!(f, "Error creating shader: {}", err), ShaderCreationError::Io(ref err) => write!(f, "couldn't read shader: {}", err),
ShaderCreationError::Compile(ref _path, ref s) => { ShaderCreationError::Compile(ref _path, ref s) => {
write!(f, "Error compiling shader: {}", s) write!(f, "failed compiling shader: {}", s)
}, },
} }
} }