Merge pull request #12 from freesig/no_unimpl

No unimpl
master
Tom 6 years ago committed by GitHub
commit c70f54ffba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -8,6 +8,6 @@ fn main() {
let mut frag_path = project_root.clone(); let mut frag_path = project_root.clone();
frag_path.push(PathBuf::from("examples/shaders/frag.glsl")); frag_path.push(PathBuf::from("examples/shaders/frag.glsl"));
let shader = sr::load(vert_path, frag_path).expect("Failed to compile"); let shader = sr::load(vert_path, frag_path).expect("Failed to compile");
let vulkano_entry = sr::parse(&shader); let vulkano_entry = sr::parse(&shader).expect("failed to parse");
dbg!(vulkano_entry); dbg!(vulkano_entry);
} }

@ -2,25 +2,24 @@ use std::fs::File;
use std::path::Path; use std::path::Path;
use shaderc::ShaderKind; use shaderc::ShaderKind;
use std::io::Read; use std::io::Read;
use crate::error::CompileError;
pub fn compile<T>(path: T, shader_kind: ShaderKind) -> shaderc::Result<Vec<u32>> pub fn compile<T>(path: T, shader_kind: ShaderKind) -> Result<Vec<u32>, CompileError>
where where
T: AsRef<Path>, T: AsRef<Path>,
{ {
// TODO Probably shouldn't create this every time. // TODO Probably shouldn't create this every time.
let mut compiler = shaderc::Compiler::new().expect("failed to create compiler"); let mut compiler = shaderc::Compiler::new().ok_or(CompileError::CreateCompiler)?;
let mut f = File::open(&path).expect("failed to open shader src"); let mut f = File::open(&path).map_err(CompileError::Open)?;
let mut src = String::new(); let mut src = String::new();
f.read_to_string(&mut src).expect("failed to read src"); f.read_to_string(&mut src).map_err(CompileError::Open)?;
let mut options = shaderc::CompileOptions::new().unwrap();
options.add_macro_definition("EP", Some("main"));
let result = compiler.compile_into_spirv( let result = compiler.compile_into_spirv(
src.as_str(), src.as_str(),
shader_kind, shader_kind,
path.as_ref().to_str().expect("failed to make path string"), path.as_ref().to_str().ok_or(CompileError::InvalidPath)?,
"main", "main",
None, None,
)?; ).map_err(CompileError::Compile)?;
let data = result.as_binary(); let data = result.as_binary();
Ok(data.to_owned()) Ok(data.to_owned())
} }

@ -1,4 +1,20 @@
#[derive(Debug)] #[derive(Debug)]
pub enum Error { pub enum Error {
Compile(CompileError),
Layout(ConvertError),
LoadingData(String),
FileWatch(notify::Error),
}
#[derive(Debug)]
pub enum ConvertError {
Unimplemented,
}
#[derive(Debug)]
pub enum CompileError {
Compile(shaderc::Error), Compile(shaderc::Error),
Open(std::io::Error),
InvalidPath,
CreateCompiler,
} }

@ -56,14 +56,14 @@ unsafe impl PipelineLayoutDesc for FragLayout {
self.layout_data.num_sets self.layout_data.num_sets
} }
fn num_bindings_in_set(&self, set: usize) -> Option<usize> { fn num_bindings_in_set(&self, set: usize) -> Option<usize> {
self.layout_data.num_bindings.get(&set).map(|&i| i) self.layout_data.num_bindings.get(&set).copied()
} }
fn descriptor(&self, set: usize, binding: usize) -> Option<DescriptorDesc> { fn descriptor(&self, set: usize, binding: usize) -> Option<DescriptorDesc> {
self.layout_data.descriptions.get(&set) self.layout_data.descriptions.get(&set)
.and_then(|s|s.get(&binding)) .and_then(|s|s.get(&binding))
.map(|desc| { .map(|desc| {
let mut desc = desc.clone(); let mut desc = desc.clone();
desc.stages = self.stages.clone(); desc.stages = self.stages;
desc desc
}) })
@ -74,8 +74,8 @@ unsafe impl PipelineLayoutDesc for FragLayout {
fn push_constants_range(&self, num: usize) -> Option<PipelineLayoutDescPcRange> { fn push_constants_range(&self, num: usize) -> Option<PipelineLayoutDescPcRange> {
self.layout_data.pc_ranges.get(num) self.layout_data.pc_ranges.get(num)
.map(|desc| { .map(|desc| {
let mut desc = desc.clone(); let mut desc = *desc;
desc.stages = self.stages.clone(); desc.stages = self.stages;
desc desc
}) })
@ -123,14 +123,14 @@ unsafe impl PipelineLayoutDesc for VertLayout {
self.layout_data.num_sets self.layout_data.num_sets
} }
fn num_bindings_in_set(&self, set: usize) -> Option<usize> { fn num_bindings_in_set(&self, set: usize) -> Option<usize> {
self.layout_data.num_bindings.get(&set).map(|&i| i) self.layout_data.num_bindings.get(&set).copied()
} }
fn descriptor(&self, set: usize, binding: usize) -> Option<DescriptorDesc> { fn descriptor(&self, set: usize, binding: usize) -> Option<DescriptorDesc> {
self.layout_data.descriptions.get(&set) self.layout_data.descriptions.get(&set)
.and_then(|s|s.get(&binding)) .and_then(|s|s.get(&binding))
.map(|desc| { .map(|desc| {
let mut desc = desc.clone(); let mut desc = desc.clone();
desc.stages = self.stages.clone(); desc.stages = self.stages;
desc desc
}) })
@ -141,8 +141,8 @@ unsafe impl PipelineLayoutDesc for VertLayout {
fn push_constants_range(&self, num: usize) -> Option<PipelineLayoutDescPcRange> { fn push_constants_range(&self, num: usize) -> Option<PipelineLayoutDescPcRange> {
self.layout_data.pc_ranges.get(num) self.layout_data.pc_ranges.get(num)
.map(|desc| { .map(|desc| {
let mut desc = desc.clone(); let mut desc = *desc;
desc.stages = self.stages.clone(); desc.stages = self.stages;
desc desc
}) })

@ -8,7 +8,7 @@ mod watch;
pub use layouts::*; pub use layouts::*;
pub use reflection::LayoutData; pub use reflection::LayoutData;
pub use watch::{Message, Watch}; pub use watch::{Message, Watch};
pub use error::Error; pub use error::{Error, ConvertError};
use spirv_reflect as sr; use spirv_reflect as sr;
use vulkano as vk; use vulkano as vk;
@ -20,16 +20,15 @@ pub struct CompiledShaders {
pub fragment: Vec<u32>, pub fragment: Vec<u32>,
} }
pub fn load<T>(vertex: T, fragment: T) -> Result<CompiledShaders, Error> pub fn load<T>(vertex: T, fragment: T) -> Result<CompiledShaders, Error>
where where
T: AsRef<Path>, T: AsRef<Path>,
{ {
let vertex = compiler::compile(vertex, ShaderKind::Vertex).map_err(|e| Error::Compile(e))?; let vertex = compiler::compile(vertex, ShaderKind::Vertex).map_err(Error::Compile)?;
let fragment = compiler::compile(fragment, ShaderKind::Fragment).map_err(|e| Error::Compile(e))?; let fragment = compiler::compile(fragment, ShaderKind::Fragment).map_err(Error::Compile)?;
Ok(CompiledShaders{ vertex, fragment }) Ok(CompiledShaders{ vertex, fragment })
} }
pub fn parse(code: &CompiledShaders) -> Entry { pub fn parse(code: &CompiledShaders) -> Result<Entry, Error> {
reflection::create_entry(code) reflection::create_entry(code)
} }

@ -1,3 +1,4 @@
use crate::error::Error;
use crate::layouts::*; use crate::layouts::*;
use crate::sr; use crate::sr;
use crate::srvk::{DescriptorDescInfo, SpirvTy}; use crate::srvk::{DescriptorDescInfo, SpirvTy};
@ -7,6 +8,7 @@ use crate::vk::pipeline::shader::ShaderInterfaceDefEntry;
use crate::CompiledShaders; use crate::CompiledShaders;
use std::borrow::Cow; use std::borrow::Cow;
use std::collections::HashMap; use std::collections::HashMap;
use std::convert::TryFrom;
pub struct ShaderInterfaces { pub struct ShaderInterfaces {
pub inputs: Vec<ShaderInterfaceDefEntry>, pub inputs: Vec<ShaderInterfaceDefEntry>,
@ -22,11 +24,11 @@ pub struct LayoutData {
pub pc_ranges: Vec<PipelineLayoutDescPcRange>, pub pc_ranges: Vec<PipelineLayoutDescPcRange>,
} }
pub fn create_entry(shaders: &CompiledShaders) -> Entry { pub fn create_entry(shaders: &CompiledShaders) -> Result<Entry, Error> {
let vertex_interfaces = create_interfaces(&shaders.vertex); let vertex_interfaces = create_interfaces(&shaders.vertex)?;
let vertex_layout = create_layouts(&shaders.vertex); let vertex_layout = create_layouts(&shaders.vertex)?;
let fragment_interfaces = create_interfaces(&shaders.fragment); let fragment_interfaces = create_interfaces(&shaders.fragment)?;
let fragment_layout = create_layouts(&shaders.fragment); let fragment_layout = create_layouts(&shaders.fragment)?;
let frag_input = FragInput { let frag_input = FragInput {
inputs: fragment_interfaces.inputs, inputs: fragment_interfaces.inputs,
}; };
@ -53,71 +55,70 @@ pub fn create_entry(shaders: &CompiledShaders) -> Entry {
}, },
layout_data: vertex_layout, layout_data: vertex_layout,
}; };
Entry { Ok(Entry {
frag_input, frag_input,
frag_output, frag_output,
vert_input, vert_input,
vert_output, vert_output,
frag_layout, frag_layout,
vert_layout, vert_layout,
} })
} }
fn create_interfaces(data: &[u32]) -> ShaderInterfaces { fn create_interfaces(data: &[u32]) -> Result<ShaderInterfaces, Error> {
sr::ShaderModule::load_u32_data(data) sr::ShaderModule::load_u32_data(data)
.map_err(|e| Error::LoadingData(e.to_string()))
.map(|m| { .map(|m| {
let inputs = m let inputs = m
.enumerate_input_variables(None) .enumerate_input_variables(None)
.map(|inputs| { .map_err(|e| Error::LoadingData(e.to_string()))
.and_then(|inputs| {
inputs inputs
.iter() .iter()
.filter(|i| { .filter(|i| {
!i.decoration_flags !i.decoration_flags
.contains(sr::types::ReflectDecorationFlags::BUILT_IN) .contains(sr::types::ReflectDecorationFlags::BUILT_IN)
}) })
.map(|i| ShaderInterfaceDefEntry { .map(|i| Ok(ShaderInterfaceDefEntry {
location: i.location..(i.location + 1), location: i.location..(i.location + 1),
format: SpirvTy::from(i.format).inner(), format: SpirvTy::try_from(i.format)?.inner(),
name: Some(Cow::from(i.name.clone())), name: Some(Cow::from(i.name.clone())),
}) }))
.collect::<Vec<ShaderInterfaceDefEntry>>() .collect::<Result<Vec<ShaderInterfaceDefEntry>, _>>()
}) });
.expect("Failed to pass inputs");
let outputs = m let outputs = m
.enumerate_output_variables(None) .enumerate_output_variables(None)
.map(|outputs| { .map_err(|e| Error::LoadingData(e.to_string()))
.and_then(|outputs| {
outputs outputs
.iter() .iter()
.filter(|i| { .filter(|i| {
!i.decoration_flags !i.decoration_flags
.contains(sr::types::ReflectDecorationFlags::BUILT_IN) .contains(sr::types::ReflectDecorationFlags::BUILT_IN)
}) })
.map(|i| ShaderInterfaceDefEntry { .map(|i| Ok(ShaderInterfaceDefEntry {
location: i.location..(i.location + 1), location: i.location..(i.location + 1),
format: SpirvTy::from(i.format).inner(), format: SpirvTy::try_from(i.format)?.inner(),
name: Some(Cow::from(i.name.clone())), name: Some(Cow::from(i.name.clone())),
}))
.collect::<Result<Vec<ShaderInterfaceDefEntry>, _>>()
});
inputs.and_then(|inputs| outputs.map(|outputs| ShaderInterfaces { inputs, outputs } ))
}) })
.collect::<Vec<ShaderInterfaceDefEntry>>() .and_then(|t| t)
})
.expect("Failed to pass outputs");
ShaderInterfaces { inputs, outputs }
})
.expect("failed to load module")
} }
fn create_layouts(data: &[u32]) -> LayoutData { fn create_layouts(data: &[u32]) -> Result<LayoutData, Error> {
sr::ShaderModule::load_u32_data(data) sr::ShaderModule::load_u32_data(data)
.map(|m| { .map(|m| {
let (num_sets, num_bindings, descriptions) = m let descs: Result<_, Error> = m
.enumerate_descriptor_sets(None) .enumerate_descriptor_sets(None)
.map(|sets| { .map_err(|e| Error::LoadingData(e.to_string()))
.and_then(|sets| {
let num_sets = sets.len(); let num_sets = sets.len();
let num_bindings = sets let num_bindings = sets
.iter() .iter()
.map(|i| { .map(|i| (i.set as usize, i.bindings.len()))
dbg!(&i);
(i.set as usize, i.bindings.len())
})
.collect::<HashMap<usize, usize>>(); .collect::<HashMap<usize, usize>>();
let descriptions = sets let descriptions = sets
.iter() .iter()
@ -130,7 +131,7 @@ fn create_layouts(data: &[u32]) -> LayoutData {
descriptor_type: b.descriptor_type, descriptor_type: b.descriptor_type,
image: b.image, image: b.image,
}; };
let ty = SpirvTy::<DescriptorDescTy>::from(info).inner(); let ty = SpirvTy::<DescriptorDescTy>::try_from(info)?.inner();
let stages = ShaderStages::none(); let stages = ShaderStages::none();
let d = DescriptorDesc { let d = DescriptorDesc {
ty, ty,
@ -140,17 +141,17 @@ fn create_layouts(data: &[u32]) -> LayoutData {
// it's correct // it's correct
readonly: true, readonly: true,
}; };
(b.binding as usize, d) Ok((b.binding as usize, d))
})
.collect::<HashMap<usize, DescriptorDesc>>();
(i.set as usize, desc)
}) })
.collect::<HashMap<usize, HashMap<usize, DescriptorDesc>>>(); .collect::<Result<HashMap<usize, DescriptorDesc>, Error>>();
(num_sets, num_bindings, descriptions) desc.and_then(|d| Ok((i.set as usize, d)))
}) })
.expect("Failed to pass descriptors"); .collect::<Result<HashMap<usize, _>, Error>>();
let (num_constants, pc_ranges) = m descriptions.map(|d| (num_sets, num_bindings, d))
});
let pcs = m
.enumerate_push_constant_blocks(None) .enumerate_push_constant_blocks(None)
.map_err(|e| Error::LoadingData(e.to_string()))
.map(|constants| { .map(|constants| {
let num_constants = constants.len(); let num_constants = constants.len();
let pc_ranges = constants let pc_ranges = constants
@ -162,15 +163,17 @@ fn create_layouts(data: &[u32]) -> LayoutData {
}) })
.collect::<Vec<PipelineLayoutDescPcRange>>(); .collect::<Vec<PipelineLayoutDescPcRange>>();
(num_constants, pc_ranges) (num_constants, pc_ranges)
}) });
.expect("Failed to pass push constants"); descs.and_then(|(num_sets, num_bindings, descriptions)| {
LayoutData { pcs.map(|(num_constants, pc_ranges)| LayoutData {
num_sets, num_sets,
num_bindings, num_bindings,
descriptions, descriptions,
num_constants, num_constants,
pc_ranges, pc_ranges,
}
}) })
.expect("failed to load module") })
})
.map_err(|e| Error::LoadingData(e.to_string()))
.and_then(|t| t)
} }

@ -1,7 +1,9 @@
use crate::sr; use crate::sr;
use crate::vk; use crate::vk;
use crate::error::{ConvertError, Error};
use vk::descriptor::descriptor::*; use vk::descriptor::descriptor::*;
use vk::format::Format; use vk::format::Format;
use std::convert::TryFrom;
pub struct SpirvTy<T> { pub struct SpirvTy<T> {
inner: T, inner: T,
@ -12,39 +14,41 @@ pub struct DescriptorDescInfo {
pub image: sr::types::ReflectImageTraits, pub image: sr::types::ReflectImageTraits,
} }
impl<T> SpirvTy<T> { impl<T> SpirvTy<T> {
pub fn inner(self) -> T { pub fn inner(self) -> T {
self.inner self.inner
} }
} }
impl From<DescriptorDescInfo> for SpirvTy<DescriptorDescTy> { impl TryFrom<DescriptorDescInfo> for SpirvTy<DescriptorDescTy> {
fn from(d: DescriptorDescInfo) -> Self { type Error = Error;
fn try_from(d: DescriptorDescInfo) -> Result<Self, Self::Error> {
use sr::types::ReflectDescriptorType as SR; use sr::types::ReflectDescriptorType as SR;
use DescriptorDescTy as VK; use DescriptorDescTy as VK;
let t = match d.descriptor_type { match d.descriptor_type {
SR::Undefined => unreachable!(), SR::Undefined => Err(ConvertError::Unimplemented),
SR::Sampler => VK::Sampler, SR::Sampler => Ok(VK::Sampler),
SR::CombinedImageSampler => VK::CombinedImageSampler(SpirvTy::from(d.image).inner()), SR::CombinedImageSampler => Ok(VK::CombinedImageSampler(SpirvTy::try_from(d.image)?.inner())),
SR::SampledImage => unreachable!(), SR::SampledImage => Err(ConvertError::Unimplemented),
SR::StorageImage => unreachable!(), SR::StorageImage => Err(ConvertError::Unimplemented),
SR::UniformTexelBuffer => unreachable!(), SR::UniformTexelBuffer => Err(ConvertError::Unimplemented),
SR::StorageTexelBuffer => unreachable!(), SR::StorageTexelBuffer => Err(ConvertError::Unimplemented),
SR::UniformBuffer => unreachable!(), SR::UniformBuffer => Err(ConvertError::Unimplemented),
SR::StorageBuffer => unreachable!(), SR::StorageBuffer => Err(ConvertError::Unimplemented),
SR::UniformBufferDynamic => unreachable!(), SR::UniformBufferDynamic => Err(ConvertError::Unimplemented),
SR::StorageBufferDynamic => unreachable!(), SR::StorageBufferDynamic => Err(ConvertError::Unimplemented),
SR::InputAttachment => unreachable!(), SR::InputAttachment => Err(ConvertError::Unimplemented),
SR::AccelerationStructureNV => unreachable!(), SR::AccelerationStructureNV => Err(ConvertError::Unimplemented),
};
SpirvTy {
inner: t,
} }
.map(|t| SpirvTy{ inner: t })
.map_err(Error::Layout)
} }
} }
impl From<sr::types::ReflectImageTraits> for SpirvTy<DescriptorImageDesc> { impl TryFrom<sr::types::ReflectImageTraits> for SpirvTy<DescriptorImageDesc> {
fn from(d: sr::types::ReflectImageTraits) -> Self { type Error = Error;
fn try_from(d: sr::types::ReflectImageTraits) -> Result<Self, Self::Error> {
let conv_array_layers = |a, d|{ let conv_array_layers = |a, d|{
if a != 0 { if a != 0 {
DescriptorImageDescArray::Arrayed{max_layers: Some(d)} DescriptorImageDescArray::Arrayed{max_layers: Some(d)}
@ -54,29 +58,31 @@ impl From<sr::types::ReflectImageTraits> for SpirvTy<DescriptorImageDesc> {
}; };
let t = DescriptorImageDesc { let t = DescriptorImageDesc {
sampled: d.sampled != 0, sampled: d.sampled != 0,
dimensions: SpirvTy::from(d.dim).inner(), dimensions: SpirvTy::try_from(d.dim)?.inner(),
// TODO figure out how to do format correctly // TODO figure out how to do format correctly
//format: Some(SpirvTy::from(d.image_format).inner()), //format: Some(SpirvTy::from(d.image_format).inner()),
format: None, format: None,
multisampled: d.ms != 0, multisampled: d.ms != 0,
array_layers: conv_array_layers(d.arrayed, d.depth), array_layers: conv_array_layers(d.arrayed, d.depth),
}; };
SpirvTy{inner: t} Ok(SpirvTy{inner: t})
} }
} }
impl From<sr::types::variable::ReflectDimension> for SpirvTy<DescriptorImageDescDimensions> { impl TryFrom<sr::types::variable::ReflectDimension> for SpirvTy<DescriptorImageDescDimensions> {
fn from(d: sr::types::variable::ReflectDimension) -> Self { type Error = Error;
fn try_from(d: sr::types::variable::ReflectDimension) -> Result<Self, Self::Error> {
use sr::types::variable::ReflectDimension::*; use sr::types::variable::ReflectDimension::*;
use DescriptorImageDescDimensions::*; use DescriptorImageDescDimensions::*;
let inner = match d { match d {
Type1d => OneDimensional, Type1d => Ok(OneDimensional),
Type2d => TwoDimensional, Type2d => Ok(TwoDimensional),
Type3d => ThreeDimensional, Type3d => Ok(ThreeDimensional),
sr::types::variable::ReflectDimension::Cube => DescriptorImageDescDimensions::Cube, sr::types::variable::ReflectDimension::Cube => Ok(DescriptorImageDescDimensions::Cube),
_ => unimplemented!(), _ => Err(ConvertError::Unimplemented),
}; }
SpirvTy{ inner } .map(|t| SpirvTy{ inner: t })
.map_err(Error::Layout)
} }
} }
@ -127,16 +133,20 @@ impl From<sr::types::image::ReflectImageFormat> for SpirvTy<Format> {
R16_UINT =>R16Uint, R16_UINT =>R16Uint,
R8_UINT =>R8Uint, R8_UINT =>R8Uint,
}; };
SpirvTy{ inner } SpirvTy{ inner };
// This function shouldn't be called yet because
// it is not implemented correctly
unreachable!()
} }
} }
impl From<sr::types::ReflectFormat> for SpirvTy<Format> { impl TryFrom<sr::types::ReflectFormat> for SpirvTy<Format> {
fn from(f: sr::types::ReflectFormat) -> Self { type Error = Error;
fn try_from(f: sr::types::ReflectFormat) -> Result<Self, Self::Error> {
use sr::types::ReflectFormat::*; use sr::types::ReflectFormat::*;
use Format::*; use Format::*;
let t = match f { let t = match f {
Undefined => unreachable!(), Undefined => Err(Error::Layout(ConvertError::Unimplemented))?,
R32_UINT => R32Uint, R32_UINT => R32Uint,
R32_SINT => R32Sint, R32_SINT => R32Sint,
R32_SFLOAT => R32Sfloat, R32_SFLOAT => R32Sfloat,
@ -150,6 +160,6 @@ impl From<sr::types::ReflectFormat> for SpirvTy<Format> {
R32G32B32A32_SINT => R32G32B32A32Sint, R32G32B32A32_SINT => R32G32B32A32Sint,
R32G32B32A32_SFLOAT => R32G32B32A32Sfloat, R32G32B32A32_SFLOAT => R32G32B32A32Sfloat,
}; };
SpirvTy { inner: t } Ok(SpirvTy { inner: t })
} }
} }

@ -25,18 +25,18 @@ pub struct Message {
} }
impl Watch { impl Watch {
pub fn new<T>(vertex: T, fragment: T) -> Self pub fn create<T>(vertex: T, fragment: T) -> Result<Self, Error>
where where
T: AsRef<Path>, T: AsRef<Path>,
{ {
let (handler, rx) = create_watch( let (handler, rx) = create_watch(
vertex.as_ref().to_path_buf(), vertex.as_ref().to_path_buf(),
fragment.as_ref().to_path_buf(), fragment.as_ref().to_path_buf(),
); )?;
Watch { Ok(Watch {
_handler: handler, _handler: handler,
rx, rx,
} })
} }
} }
@ -56,7 +56,8 @@ impl Loader {
match crate::load(&self.vertex, &self.fragment) { match crate::load(&self.vertex, &self.fragment) {
Ok(shaders) => { Ok(shaders) => {
let entry = crate::parse(&shaders); let entry = crate::parse(&shaders);
self.tx.send(Ok(Message { shaders, entry })).ok() let msg = entry.map(|entry| Message { shaders, entry });
self.tx.send(msg).ok()
} }
Err(e) => self.tx.send(Err(e)).ok(), Err(e) => self.tx.send(Err(e)).ok(),
}; };
@ -79,31 +80,33 @@ impl Drop for Handler {
} }
fn create_watch( fn create_watch(
mut vert_path: PathBuf, vert_path: PathBuf,
mut frag_path: PathBuf, frag_path: PathBuf,
) -> (Handler, mpsc::Receiver<Result<Message, Error>>) { ) -> Result<(Handler, mpsc::Receiver<Result<Message, Error>>), Error> {
let (notify_tx, notify_rx) = mpsc::channel(); let (notify_tx, notify_rx) = mpsc::channel();
let (thread_tx, thread_rx) = mpsc::channel(); let (thread_tx, thread_rx) = mpsc::channel();
let mut watcher: RecommendedWatcher = let mut watcher: RecommendedWatcher =
Watcher::new(notify_tx, Duration::from_millis(50)).expect("failed to create watcher"); Watcher::new(notify_tx, Duration::from_millis(50)).map_err(Error::FileWatch)?;
vert_path.pop(); let mut vp = vert_path.clone();
frag_path.pop(); let mut fp = frag_path.clone();
vp.pop();
fp.pop();
watcher watcher
.watch(&vert_path, RecursiveMode::NonRecursive) .watch(&vp, RecursiveMode::NonRecursive)
.expect("failed to add vertex shader to notify"); .map_err(Error::FileWatch)?;
watcher watcher
.watch(&frag_path, RecursiveMode::NonRecursive) .watch(&fp, RecursiveMode::NonRecursive)
.expect("failed to add fragment shader to notify"); .map_err(Error::FileWatch)?;
let (loader, rx) = Loader::create(vert_path, frag_path); let (loader, rx) = Loader::create(vert_path, frag_path);
let handle = thread::spawn(move || 'watch_loop: loop { let handle = thread::spawn(move || 'watch_loop: loop {
if let Ok(_) = thread_rx.try_recv() { if thread_rx.try_recv().is_ok() {
break 'watch_loop; break 'watch_loop;
} }
if let Ok(notify::DebouncedEvent::Create(_)) if let Ok(notify::DebouncedEvent::Create(_)) | Ok(notify::DebouncedEvent::Write(_)) =
| Ok(notify::DebouncedEvent::Write(_)) = notify_rx.recv_timeout(Duration::from_secs(1)) notify_rx.recv_timeout(Duration::from_secs(1))
{ {
loader.reload(); loader.reload();
} }
@ -114,5 +117,5 @@ fn create_watch(
handle, handle,
_watcher: watcher, _watcher: watcher,
}; };
(handler, rx) Ok((handler, rx))
} }

@ -65,7 +65,7 @@ where
let mut fragment_path = path.clone(); let mut fragment_path = path.clone();
fragment_path.push(fragment); fragment_path.push(fragment);
let shader = shade_runner::load(vertex_path, fragment_path).expect("Failed to compile"); let shader = shade_runner::load(vertex_path, fragment_path).expect("Failed to compile");
shade_runner::parse(&shader) shade_runner::parse(&shader).unwrap()
} }
fn do_test<T>(a: &T, b: &T) fn do_test<T>(a: &T, b: &T)

Loading…
Cancel
Save