reload shaders

This commit is contained in:
2019-07-24 21:10:16 +02:00
parent cf0516b212
commit 007e158410
3 changed files with 82 additions and 55 deletions

View File

@@ -7,6 +7,9 @@
<sourceFolder url="file://$MODULE_DIR$/examples" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/examples" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" /> <sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/benches" isTestSource="true" /> <sourceFolder url="file://$MODULE_DIR$/benches" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/../rust-engine\examples" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../rust-engine\tests" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/../rust-engine\benches" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/target" /> <excludeFolder url="file://$MODULE_DIR$/target" />
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />

View File

@@ -1,5 +1,5 @@
use crate::vulkan::{Vertex, GameData}; use crate::vulkan::{Vertex, GameData};
use winit::{Event, WindowEvent}; use winit::{Event, WindowEvent, ElementState};
use std::time::SystemTime; use std::time::SystemTime;
use std::iter::FromIterator; use std::iter::FromIterator;
@@ -7,7 +7,7 @@ mod vulkan;
impl GameData<'_> { impl GameData<'_> {
/// Returns true if event should be ignored by the vulkan handler /// Returns true if event should be ignored by the vulkan handler
fn on_window_event(self: &Self, event: &Event) -> bool { fn on_window_event(self: &mut Self, event: &Event) -> bool {
match event { match event {
Event::WindowEvent { event: WindowEvent::KeyboardInput { device_id, input }, .. } => { Event::WindowEvent { event: WindowEvent::KeyboardInput { device_id, input }, .. } => {
let mods = String::from_iter( let mods = String::from_iter(
@@ -20,6 +20,10 @@ impl GameData<'_> {
} else { } else {
println!("Keyboard {:?} input {:?} {:?}", device_id, input.state, input.scancode) println!("Keyboard {:?} input {:?} {:?}", device_id, input.state, input.scancode)
} }
if input.state == ElementState::Released && input.modifiers.ctrl && input.scancode == 19 {
self.recreate_pipeline = true;
}
} }
_ => {} _ => {}
} }
@@ -52,7 +56,8 @@ fn main() {
Vertex { position: [0.9, 0., 0.] }, Vertex { position: [0.9, 0., 0.] },
], ],
push_constants: &mut pc, push_constants: &mut pc,
start_time: SystemTime::now() start_time: SystemTime::now(),
recreate_pipeline: false
}; };
vulkan::init(data); vulkan::init(data);

View File

@@ -50,6 +50,7 @@ pub struct GameData<'a> {
pub mesh_vertices: Vec<Vertex>, pub mesh_vertices: Vec<Vertex>,
pub line_vertices: Vec<Vertex>, pub line_vertices: Vec<Vertex>,
pub push_constants: &'a mut PushConstants, pub push_constants: &'a mut PushConstants,
pub recreate_pipeline: bool,
} }
pub fn init(mut game: GameData) { pub fn init(mut game: GameData) {
@@ -92,7 +93,7 @@ pub fn init(mut game: GameData) {
error: true, error: true,
warning: true, warning: true,
performance_warning: true, performance_warning: true,
information: true, information: false,
debug: true, debug: true,
}; };
@@ -237,13 +238,13 @@ pub fn init(mut game: GameData) {
let sub_pass = Subpass::from(render_pass.clone(), 0).unwrap(); let sub_pass = Subpass::from(render_pass.clone(), 0).unwrap();
let pipeline = create_pipeline(device.clone(), sub_pass.clone()); let mut pipeline = create_pipeline(device.clone(), sub_pass.clone()).unwrap();
let line_shader_vertex_entry; let line_shader_vertex_entry;
let line_shader_fragment_entry; let line_shader_fragment_entry;
let line_shader_module_vertex; let line_shader_module_vertex;
let line_shader_module_fragment; let line_shader_module_fragment;
let (line_shader, line_shader_data) = read_shader("shaders/line.vert", "shaders/line.frag"); let (line_shader, line_shader_data) = read_shader("shaders/line.vert", "shaders/line.frag").unwrap();
unsafe { unsafe {
line_shader_module_vertex = ShaderModule::from_words(device.clone(), &line_shader.vertex).expect("Failed to load"); line_shader_module_vertex = ShaderModule::from_words(device.clone(), &line_shader.vertex).expect("Failed to load");
line_shader_vertex_entry = line_shader_module_vertex.graphics_entry_point( line_shader_vertex_entry = line_shader_module_vertex.graphics_entry_point(
@@ -335,6 +336,16 @@ pub fn init(mut game: GameData) {
recreate_swapchain = false; recreate_swapchain = false;
} }
if game.recreate_pipeline {
if let Some(pipeline_ok) = create_pipeline(device.clone(), sub_pass.clone()) {
pipeline = pipeline_ok;
println!("Updated pipeline.");
} else {
println!("Failed to update pipeline.");
}
game.recreate_pipeline = false;
}
// Before we can draw on the output, we have to *acquire* an image from the swapchain. If // Before we can draw on the output, we have to *acquire* an image from the swapchain. If
// no image is available (which happens if you submit draw commands too quickly), then the // no image is available (which happens if you submit draw commands too quickly), then the
// function will block. // function will block.
@@ -464,12 +475,13 @@ fn window_size_dependent_setup(
}).collect::<Vec<_>>() }).collect::<Vec<_>>()
} }
fn create_pipeline<T: RenderPassAbstract>(device: Arc<Device>, sub_pass: Subpass<Arc<T>>) -> Arc<GraphicsPipeline<SingleBufferDefinition<Vertex>, Box<dyn PipelineLayoutAbstract + Send + Sync>, Arc<T>>> { fn create_pipeline<T: RenderPassAbstract>(device: Arc<Device>, sub_pass: Subpass<Arc<T>>) -> Option<Arc<GraphicsPipeline<SingleBufferDefinition<Vertex>, Box<dyn PipelineLayoutAbstract + Send + Sync>, Arc<T>>>> {
if let Some((mesh_shader, mesh_shader_data)) = read_shader("shaders/triangle.vert", "shaders/triangle.frag") {
let mesh_shader_vertex_entry; let mesh_shader_vertex_entry;
let mesh_shader_fragment_entry; let mesh_shader_fragment_entry;
let mesh_shader_module_vertex; let mesh_shader_module_vertex;
let mesh_shader_module_fragment; let mesh_shader_module_fragment;
let (mesh_shader, mesh_shader_data) = read_shader("shaders/triangle.vert", "shaders/triangle.frag");
unsafe { unsafe {
mesh_shader_module_vertex = ShaderModule::from_words(device.clone(), &mesh_shader.vertex).expect("Failed to load"); mesh_shader_module_vertex = ShaderModule::from_words(device.clone(), &mesh_shader.vertex).expect("Failed to load");
mesh_shader_vertex_entry = mesh_shader_module_vertex.graphics_entry_point( mesh_shader_vertex_entry = mesh_shader_module_vertex.graphics_entry_point(
@@ -509,10 +521,13 @@ fn create_pipeline<T: RenderPassAbstract>(device: Arc<Device>, sub_pass: Subpass
.build(device.clone()) .build(device.clone())
.unwrap()); .unwrap());
return pipeline; return Some(pipeline);
} else {
return None;
}
} }
fn read_shader(vert_path_relative: &str, frag_path_relative: &str) -> (CompiledShaders, Entry) { fn read_shader(vert_path_relative: &str, frag_path_relative: &str) -> Option<(CompiledShaders, Entry)> {
let project_root = std::env::current_dir().expect("failed to get root directory"); let project_root = std::env::current_dir().expect("failed to get root directory");
let mut vert_path = project_root.clone(); let mut vert_path = project_root.clone();
@@ -525,11 +540,15 @@ fn read_shader(vert_path_relative: &str, frag_path_relative: &str) -> (CompiledS
match shader_result { match shader_result {
Ok(shader) => { Ok(shader) => {
let shader_data = shade_runner::parse(&shader).expect("Failed to parse"); let shader_data = shade_runner::parse(&shader).expect("Failed to parse");
return (shader, shader_data); return Some((shader, shader_data));
} }
Err(shade_runner::error::Error::Compile(shade_runner::error::CompileError::Compile(shaderc::Error::CompilationError(line, error)))) => { Err(shade_runner::error::Error::Compile(shade_runner::error::CompileError::Compile(shaderc::Error::CompilationError(line, error)))) => {
panic!("Shader line {}: {:?}", line, error); println!("Shader line {}: {:?}", line, error);
return None;
}
Err(error) => {
println!("Shader compilation error: {:?}", error);
return None;
} }
Err(error) => panic!("Shader compilation error: {:?}", error)
} }
} }