1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use std::collections::HashSet;
use std::path::PathBuf;
use vulkano::pipeline::GraphicsPipelineAbstract;
use vulkano::framebuffer::RenderPassAbstract;
use std::sync::Arc;
use vulkano::pipeline::shader::{ShaderModule, GraphicsShaderType, GeometryShaderExecutionMode};
use vulkano::device::Device;
use shade_runner::Entry;
use shaderc::ShaderKind;
use crate::canvas::managed::handles::CompiledShaderHandle;
use vulkano::pipeline::vertex::Vertex;
pub trait CompiledShaderResources {
fn get_path(filename: String, shader_type: 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 shader_path = shader_path.clone();
match shader_type {
ShaderType::VERTEX => {
shader_path.push(PathBuf::from(filename.clone() + ".vert"));
}
ShaderType::FRAGMENT => {
shader_path.push(PathBuf::from(filename.clone() + ".frag"));
}
ShaderType::GEOMETRY => {
shader_path.push(PathBuf::from(filename.clone() + ".geom"));
}
ShaderType::TESSELLATION_CONTROL => {
shader_path.push(PathBuf::from(filename.clone() + ".tesscont"));
}
ShaderType::TESSELLATION_EVALUATION => {
shader_path.push(PathBuf::from(filename.clone() + ".tesseval"));
}
}
shader_path
}
fn compile(filepath: PathBuf, device: Arc<Device>, shader_type: ShaderType) -> (Entry, Arc<ShaderModule>) {
let compiled_shader = shade_runner::load(filepath, Self::convert_sr(shader_type))
.expect("Shader didn't compile");
let vulkano_entry =
shade_runner::parse(&compiled_shader)
.expect("failed to parse");
(vulkano_entry, unsafe {
ShaderModule::from_words(device.clone(), &compiled_shader.spriv.clone())
}.unwrap())
}
fn convert_vk(shader_type: ShaderType) -> GraphicsShaderType {
match shader_type {
ShaderType::VERTEX => { GraphicsShaderType::Vertex }
ShaderType::FRAGMENT => { GraphicsShaderType::Fragment }
ShaderType::GEOMETRY => { GraphicsShaderType::Geometry(GeometryShaderExecutionMode::Triangles) }
ShaderType::TESSELLATION_CONTROL => { GraphicsShaderType::TessellationControl }
ShaderType::TESSELLATION_EVALUATION => { GraphicsShaderType::TessellationEvaluation }
}
}
fn convert_sr(shader_type: ShaderType) -> ShaderKind {
match shader_type {
ShaderType::VERTEX => { ShaderKind::Vertex }
ShaderType::FRAGMENT => { ShaderKind::Fragment }
ShaderType::GEOMETRY => { ShaderKind::Geometry }
ShaderType::TESSELLATION_CONTROL => { ShaderKind::TessControl }
ShaderType::TESSELLATION_EVALUATION => { ShaderKind::TessEvaluation }
}
}
}
pub trait CompiledShader {
fn new<V>(filename: String,
device: Arc<Device>,
handle: Arc<CompiledShaderHandle>,
render_pass: Arc<dyn RenderPassAbstract + Send + Sync>) -> Self where Self: Sized, V: Vertex,;
fn get_name(&self) -> String;
fn get_handle(&self) -> Arc<CompiledShaderHandle>;
fn get_pipeline(&self) -> Arc<dyn GraphicsPipelineAbstract + Sync + Send>;
fn get_renderpass(&self) -> Arc<dyn RenderPassAbstract + Send + Sync>;
fn recompile<V: Vertex>(self, render_pass: Arc<dyn RenderPassAbstract + Send + Sync>)
-> Self where Self: Sized;
}
#[derive(PartialEq, Eq, Hash, Clone)]
pub enum ShaderType {
VERTEX = 0,
FRAGMENT = 1,
GEOMETRY = 2,
TESSELLATION_CONTROL = 3,
TESSELLATION_EVALUATION = 4,
}