@@ -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())
|
||||||
}
|
}
|
||||||
|
|||||||
18
src/error.rs
18
src/error.rs
@@ -1,4 +1,20 @@
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
Compile(shaderc::Error),
|
Compile(CompileError),
|
||||||
|
Layout(ConvertError),
|
||||||
|
LoadingData(String),
|
||||||
|
FileWatch(notify::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ConvertError {
|
||||||
|
Unimplemented,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum CompileError {
|
||||||
|
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>>();
|
.collect::<Result<HashMap<usize, DescriptorDesc>, Error>>();
|
||||||
(i.set as usize, desc)
|
desc.and_then(|d| Ok((i.set as usize, d)))
|
||||||
})
|
})
|
||||||
.collect::<HashMap<usize, HashMap<usize, DescriptorDesc>>>();
|
.collect::<Result<HashMap<usize, _>, Error>>();
|
||||||
(num_sets, num_bindings, descriptions)
|
descriptions.map(|d| (num_sets, num_bindings, d))
|
||||||
})
|
});
|
||||||
.expect("Failed to pass descriptors");
|
let pcs = m
|
||||||
let (num_constants, pc_ranges) = 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)
|
||||||
}
|
}
|
||||||
|
|||||||
86
src/srvk.rs
86
src/srvk.rs
@@ -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 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
41
src/watch.rs
41
src/watch.rs
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user