|
|
|
@ -13,6 +13,47 @@ use crate::util::vertex_3d::Vertex3D;
|
|
|
|
|
use vulkano::pipeline::depth_stencil::{DepthStencil, Stencil, StencilOp, Compare, DepthBounds};
|
|
|
|
|
use std::collections::HashSet;
|
|
|
|
|
|
|
|
|
|
/// Inheriting this gives private functions to grab resources
|
|
|
|
|
trait CompiledGraphicsPipelineResources {
|
|
|
|
|
fn get_paths(filename: String, types: HashSet<ShaderType>) -> Vec<(ShaderType, PathBuf)> {
|
|
|
|
|
let project_root =
|
|
|
|
|
std::env::current_dir()
|
|
|
|
|
.expect("failed to get root directory");
|
|
|
|
|
|
|
|
|
|
let mut shader_path = project_root.clone();
|
|
|
|
|
shader_path.push(PathBuf::from("resources/shaders/"));
|
|
|
|
|
|
|
|
|
|
let mut paths = Vec::new();
|
|
|
|
|
|
|
|
|
|
for shader_type in types {
|
|
|
|
|
match shader_type {
|
|
|
|
|
ShaderType::VERTEX => {
|
|
|
|
|
let mut shader_path = shader_path.clone();
|
|
|
|
|
shader_path.push(PathBuf::from(filename.clone() + ".vert"));
|
|
|
|
|
paths.push((shader_type, shader_path));
|
|
|
|
|
}
|
|
|
|
|
ShaderType::FRAGMENT => {
|
|
|
|
|
let mut shader_path = shader_path.clone();
|
|
|
|
|
shader_path.push(PathBuf::from(filename.clone() + ".frag"));
|
|
|
|
|
paths.push((shader_type, shader_path));
|
|
|
|
|
}
|
|
|
|
|
ShaderType::GEOMETRY => {
|
|
|
|
|
let mut shader_path = shader_path.clone();
|
|
|
|
|
shader_path.push(PathBuf::from(filename.clone() + ".geom"));
|
|
|
|
|
paths.push((shader_type, shader_path));
|
|
|
|
|
}
|
|
|
|
|
ShaderType::TESSELLATION => {
|
|
|
|
|
let mut shader_path = shader_path.clone();
|
|
|
|
|
shader_path.push(PathBuf::from(filename.clone() + ".tess"));
|
|
|
|
|
paths.push((shader_type, shader_path));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
paths
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Typed wrapper for a u32 handle
|
|
|
|
|
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
|
|
|
|
|
pub struct CompiledGraphicsPipelineHandle {
|
|
|
|
@ -20,32 +61,11 @@ pub struct CompiledGraphicsPipelineHandle {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub trait CompiledGraphicsPipeline {
|
|
|
|
|
// fn get_paths(&self, filename: String) -> Vec<(ShaderType, PathBuf)> {
|
|
|
|
|
//
|
|
|
|
|
// let project_root =
|
|
|
|
|
// std::env::current_dir()
|
|
|
|
|
// .expect("failed to get root directory");
|
|
|
|
|
//
|
|
|
|
|
// let mut shader_path = project_root.clone();
|
|
|
|
|
// shader_path.push(PathBuf::from("resources/shaders/"));
|
|
|
|
|
//
|
|
|
|
|
//
|
|
|
|
|
//
|
|
|
|
|
// let mut vertex_shader_path = shader_path.clone();
|
|
|
|
|
// vertex_shader_path.push(PathBuf::from("resources/shaders/"));
|
|
|
|
|
// vertex_shader_path.push(PathBuf::from(filename.clone() + ".vertex"));
|
|
|
|
|
//
|
|
|
|
|
// let mut fragment_shader_path = project_root.clone();
|
|
|
|
|
// fragment_shader_path.push(PathBuf::from("resources/shaders/"));
|
|
|
|
|
// fragment_shader_path.push(PathBuf::from(filename.clone() + ".fragment"));
|
|
|
|
|
//
|
|
|
|
|
// (vertex_shader_path, fragment_shader_path)
|
|
|
|
|
// }
|
|
|
|
|
fn new(filename: String, shaders: HashSet<ShaderType>) -> Self;
|
|
|
|
|
fn get_name() -> String;
|
|
|
|
|
fn get_handle() -> Arc<CompiledGraphicsPipelineHandle>;
|
|
|
|
|
fn get_pipeline() -> Arc<dyn GraphicsPipelineAbstract + Sync + Send>;
|
|
|
|
|
fn recompile();
|
|
|
|
|
fn get_name(&self) -> String;
|
|
|
|
|
fn get_handle(&self) -> Arc<CompiledGraphicsPipelineHandle>;
|
|
|
|
|
fn get_pipeline(&self) -> Arc<dyn GraphicsPipelineAbstract + Sync + Send>;
|
|
|
|
|
fn recompile(self, render_pass: Arc<dyn RenderPassAbstract + Send + Sync>)
|
|
|
|
|
-> Self where Self: Sized;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Legacy ShaderType enum for single type shaders.
|
|
|
|
@ -54,7 +74,8 @@ pub enum ShaderType {
|
|
|
|
|
VERTEX = 0,
|
|
|
|
|
FRAGMENT = 1,
|
|
|
|
|
GEOMETRY = 2,
|
|
|
|
|
TESSELATION = 3,
|
|
|
|
|
TESSELLATION_CONTROL = 3,
|
|
|
|
|
TESSELLATION_EVALUATION = 4,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -66,121 +87,96 @@ pub struct CanvasShaderHandle {
|
|
|
|
|
|
|
|
|
|
/// CanvasShader holds the pipeline and render pass for the input shader source
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub struct CanvasShader {
|
|
|
|
|
|
|
|
|
|
pub struct GenericShader {
|
|
|
|
|
graphics_pipeline: Option<Arc<dyn GraphicsPipelineAbstract + Sync + Send>>,
|
|
|
|
|
|
|
|
|
|
handle: Arc<CompiledGraphicsPipelineHandle>,
|
|
|
|
|
name: String,
|
|
|
|
|
shader_types: HashSet<ShaderType>,
|
|
|
|
|
|
|
|
|
|
device: Arc<Device>,
|
|
|
|
|
pub(crate) handle: Arc<CanvasShaderHandle>,
|
|
|
|
|
pub(crate) name: String,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl CompiledGraphicsPipeline for CanvasShader {
|
|
|
|
|
|
|
|
|
|
// fn get_path(filename: String) -> (PathBuf, PathBuf) {
|
|
|
|
|
// let project_root =
|
|
|
|
|
// std::env::current_dir()
|
|
|
|
|
// .expect("failed to get root directory");
|
|
|
|
|
//
|
|
|
|
|
// let mut shader_path = project_root.clone();
|
|
|
|
|
// shader_path.push(PathBuf::from("resources/shaders/"));
|
|
|
|
|
//
|
|
|
|
|
// let mut vertex_shader_path = project_root.clone();
|
|
|
|
|
// vertex_shader_path.push(PathBuf::from("resources/shaders/"));
|
|
|
|
|
// vertex_shader_path.push(PathBuf::from(filename.clone() + ".vertex"));
|
|
|
|
|
//
|
|
|
|
|
// let mut fragment_shader_path = project_root.clone();
|
|
|
|
|
// fragment_shader_path.push(PathBuf::from("resources/shaders/"));
|
|
|
|
|
// fragment_shader_path.push(PathBuf::from(filename.clone() + ".fragment"));
|
|
|
|
|
//
|
|
|
|
|
// (vertex_shader_path, fragment_shader_path)
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
fn new(filename: String, shaders: HashSet<ShaderType>) -> Self {
|
|
|
|
|
unimplemented!()
|
|
|
|
|
}
|
|
|
|
|
/// Gives CanvasShader the resource functions
|
|
|
|
|
impl CompiledGraphicsPipelineResources for GenericShader {}
|
|
|
|
|
|
|
|
|
|
fn get_name() -> String {
|
|
|
|
|
unimplemented!()
|
|
|
|
|
/// Convenience interface so we don't have to juggle shader types
|
|
|
|
|
impl CompiledGraphicsPipeline for GenericShader {
|
|
|
|
|
fn get_name(&self) -> String {
|
|
|
|
|
self.name.clone()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn get_handle() -> Arc<CompiledGraphicsPipelineHandle> {
|
|
|
|
|
unimplemented!()
|
|
|
|
|
fn get_handle(&self) -> Arc<CompiledGraphicsPipelineHandle> {
|
|
|
|
|
self.handle.clone()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn get_pipeline() -> Arc<dyn GraphicsPipelineAbstract + Sync + Send> {
|
|
|
|
|
unimplemented!()
|
|
|
|
|
fn get_pipeline(&self) -> Arc<dyn GraphicsPipelineAbstract + Sync + Send> {
|
|
|
|
|
self.graphics_pipeline.clone().unwrap()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn recompile() {
|
|
|
|
|
unimplemented!()
|
|
|
|
|
fn recompile(self, render_pass: Arc<dyn RenderPassAbstract + Send + Sync>) -> GenericShader {
|
|
|
|
|
GenericShader::new(self.name,
|
|
|
|
|
self.shader_types,
|
|
|
|
|
self.device,
|
|
|
|
|
self.handle,
|
|
|
|
|
render_pass.clone())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl CanvasShader {
|
|
|
|
|
impl GenericShader {
|
|
|
|
|
|
|
|
|
|
fn get_path(filename: String) -> (PathBuf, PathBuf) {
|
|
|
|
|
let project_root =
|
|
|
|
|
std::env::current_dir()
|
|
|
|
|
.expect("failed to get root directory");
|
|
|
|
|
/// This will explode when the shader does not want to compile
|
|
|
|
|
pub fn new(filename: String,
|
|
|
|
|
shader_types: HashSet<ShaderType>,
|
|
|
|
|
device: Arc<Device>,
|
|
|
|
|
handle: Arc<CompiledGraphicsPipelineHandle>,
|
|
|
|
|
render_pass: Arc<dyn RenderPassAbstract + Send + Sync>) -> GenericShader {
|
|
|
|
|
|
|
|
|
|
let mut shader_path = project_root.clone();
|
|
|
|
|
shader_path.push(PathBuf::from("resources/shaders/"));
|
|
|
|
|
let filenames = GenericShader::get_paths(filename.clone(), shader_types.clone());
|
|
|
|
|
|
|
|
|
|
let mut vertex_shader_path = project_root.clone();
|
|
|
|
|
vertex_shader_path.push(PathBuf::from("resources/shaders/"));
|
|
|
|
|
vertex_shader_path.push(PathBuf::from(filename.clone() + ".vertex"));
|
|
|
|
|
// TODO: better compile message, run til successful compile
|
|
|
|
|
|
|
|
|
|
let mut fragment_shader_path = project_root.clone();
|
|
|
|
|
fragment_shader_path.push(PathBuf::from("resources/shaders/"));
|
|
|
|
|
fragment_shader_path.push(PathBuf::from(filename.clone() + ".fragment"));
|
|
|
|
|
|
|
|
|
|
(vertex_shader_path, fragment_shader_path)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Clone and returns the compiled graphics pipeline
|
|
|
|
|
pub fn get_pipeline(&self) -> Arc<dyn GraphicsPipelineAbstract + Sync + Send> {
|
|
|
|
|
self.graphics_pipeline.clone().unwrap()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Create a new shader.
|
|
|
|
|
/// This will explode when the shader does not want to compile
|
|
|
|
|
pub fn new(filename: String,
|
|
|
|
|
capabilities: Capabilities,
|
|
|
|
|
queue: Arc<Queue>,
|
|
|
|
|
physical: PhysicalDevice,
|
|
|
|
|
device: Arc<Device>,
|
|
|
|
|
handle: Arc<CanvasShaderHandle>,
|
|
|
|
|
render_pass: Arc<dyn RenderPassAbstract + Send + Sync>,) -> CanvasShader {
|
|
|
|
|
for shader in filenames {
|
|
|
|
|
match shader.0 {
|
|
|
|
|
ShaderType::VERTEX => {
|
|
|
|
|
let shader = sr::load(filenames.0, filenames.1)
|
|
|
|
|
.expect("Shader didn't compile");
|
|
|
|
|
|
|
|
|
|
let format = capabilities.supported_formats[0].0;
|
|
|
|
|
let vulkano_entry =
|
|
|
|
|
sr::parse(&shader)
|
|
|
|
|
.expect("failed to parse");
|
|
|
|
|
}
|
|
|
|
|
ShaderType::FRAGMENT => {
|
|
|
|
|
|
|
|
|
|
let filenames = CanvasShader::get_path(filename.clone());
|
|
|
|
|
}
|
|
|
|
|
ShaderType::GEOMETRY => {
|
|
|
|
|
|
|
|
|
|
// TODO: better compile message, run til successful compile
|
|
|
|
|
let shader = sr::load(filenames.0, filenames.1)
|
|
|
|
|
.expect("Shader didn't compile");
|
|
|
|
|
}
|
|
|
|
|
ShaderType::TESSELLATION => {
|
|
|
|
|
|
|
|
|
|
let vulkano_entry =
|
|
|
|
|
sr::parse(&shader)
|
|
|
|
|
.expect("failed to parse");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let fragment_shader_module: Arc<ShaderModule> = unsafe {
|
|
|
|
|
let filenames1 = CanvasShader::get_path(filename.clone());
|
|
|
|
|
let filenames1 = GenericShader::get_path(filename.clone());
|
|
|
|
|
let shader1 = sr::load(filenames1.0, filenames1.1)
|
|
|
|
|
.expect("Shader didn't compile");
|
|
|
|
|
vulkano::pipeline::shader::ShaderModule::from_words(device.clone(), &shader1.fragment.clone())
|
|
|
|
|
ShaderModule::from_words(device.clone(), &shader1.fragment.clone())
|
|
|
|
|
}.unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let vertex_shader_module: Arc<ShaderModule> = unsafe {
|
|
|
|
|
let filenames1 = CanvasShader::get_path(filename.clone());
|
|
|
|
|
|
|
|
|
|
let filenames1 = GenericShader::get_path(filename.clone());
|
|
|
|
|
let shader1 = sr::load(filenames1.0, filenames1.1)
|
|
|
|
|
.expect("Shader didn't compile");
|
|
|
|
|
vulkano::pipeline::shader::ShaderModule::from_words(device.clone(), &shader1.vertex.clone())
|
|
|
|
|
ShaderModule::from_words(device.clone(), &shader1.vertex.clone())
|
|
|
|
|
}.unwrap();
|
|
|
|
|
|
|
|
|
|
let filenames = CanvasShader::get_path(filename.clone());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let frag_entry_point = unsafe {
|
|
|
|
|
Some(fragment_shader_module.graphics_entry_point(CStr::from_bytes_with_nul_unchecked(b"main\0"),
|
|
|
|
@ -199,31 +195,31 @@ impl CanvasShader {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let stencil = DepthStencil {
|
|
|
|
|
depth_compare: Compare::Less,
|
|
|
|
|
depth_write: true,
|
|
|
|
|
depth_bounds_test: DepthBounds::Disabled,
|
|
|
|
|
stencil_front: Stencil {
|
|
|
|
|
compare: Compare::Equal,
|
|
|
|
|
pass_op: StencilOp::IncrementAndWrap,
|
|
|
|
|
fail_op: StencilOp::DecrementAndClamp,
|
|
|
|
|
depth_fail_op: StencilOp::Keep,
|
|
|
|
|
compare_mask: None,
|
|
|
|
|
write_mask: None,
|
|
|
|
|
reference: None,
|
|
|
|
|
},
|
|
|
|
|
stencil_back: Stencil {
|
|
|
|
|
compare: Compare::Equal,
|
|
|
|
|
pass_op: StencilOp::Invert,
|
|
|
|
|
fail_op: StencilOp::Zero,
|
|
|
|
|
depth_fail_op: StencilOp::Zero,
|
|
|
|
|
compare_mask: None,
|
|
|
|
|
write_mask: None,
|
|
|
|
|
reference: None,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CanvasShader {
|
|
|
|
|
depth_compare: Compare::Less,
|
|
|
|
|
depth_write: true,
|
|
|
|
|
depth_bounds_test: DepthBounds::Disabled,
|
|
|
|
|
stencil_front: Stencil {
|
|
|
|
|
compare: Compare::Equal,
|
|
|
|
|
pass_op: StencilOp::IncrementAndWrap,
|
|
|
|
|
fail_op: StencilOp::DecrementAndClamp,
|
|
|
|
|
depth_fail_op: StencilOp::Keep,
|
|
|
|
|
compare_mask: None,
|
|
|
|
|
write_mask: None,
|
|
|
|
|
reference: None,
|
|
|
|
|
},
|
|
|
|
|
stencil_back: Stencil {
|
|
|
|
|
compare: Compare::Equal,
|
|
|
|
|
pass_op: StencilOp::Invert,
|
|
|
|
|
fail_op: StencilOp::Zero,
|
|
|
|
|
depth_fail_op: StencilOp::Zero,
|
|
|
|
|
compare_mask: None,
|
|
|
|
|
write_mask: None,
|
|
|
|
|
reference: None,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GenericShader {
|
|
|
|
|
graphics_pipeline: Some(Arc::new(GraphicsPipeline::start()
|
|
|
|
|
|
|
|
|
|
.vertex_input(SingleBufferDefinition::<Vertex3D>::new())
|
|
|
|
@ -256,6 +252,7 @@ impl CanvasShader {
|
|
|
|
|
device: device,
|
|
|
|
|
handle: handle.clone(),
|
|
|
|
|
name: filename.clone(),
|
|
|
|
|
shader_types: shader_types.clone(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|