mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-07-08 00:05:00 +00:00
Caching for resources is now used instead of ignored
This commit is contained in:
parent
38b36ed4c6
commit
59cb448872
7 changed files with 84 additions and 94 deletions
|
@ -1,6 +1,5 @@
|
|||
// use super::render_state::RenderState;
|
||||
use super::color_palette::ColorPalette;
|
||||
use super::gui_rect::GuiRect;
|
||||
use super::window_events;
|
||||
use super::pipeline::Pipeline;
|
||||
use super::texture::Texture;
|
||||
use super::shader_stage::compile_from_glsl;
|
||||
|
@ -9,8 +8,7 @@ use super::draw_command::DrawCommand;
|
|||
use super::gui_tree::GuiTree;
|
||||
use std::collections::VecDeque;
|
||||
use winit::event::*;
|
||||
use winit::event_loop::ControlFlow;
|
||||
use winit::event_loop::EventLoop;
|
||||
use winit::event_loop::*;
|
||||
use winit::window::Window;
|
||||
use futures::executor::block_on;
|
||||
|
||||
|
@ -111,13 +109,17 @@ impl Application {
|
|||
|
||||
// Load the vertex shader
|
||||
let vertex_shader_path = "shaders/shader.vert";
|
||||
let vertex_shader_module = compile_from_glsl(&self.device, vertex_shader_path, glsl_to_spirv::ShaderType::Vertex).unwrap();
|
||||
self.shader_cache.set(vertex_shader_path, vertex_shader_module);
|
||||
if self.shader_cache.get(vertex_shader_path).is_none() {
|
||||
let vertex_shader_module = compile_from_glsl(&self.device, vertex_shader_path, glsl_to_spirv::ShaderType::Vertex).unwrap();
|
||||
self.shader_cache.set(vertex_shader_path, vertex_shader_module);
|
||||
}
|
||||
|
||||
// Load the fragment shader
|
||||
let fragment_shader_path = "shaders/shader.frag";
|
||||
let fragment_shader_module = compile_from_glsl(&self.device, fragment_shader_path, glsl_to_spirv::ShaderType::Fragment).unwrap();
|
||||
self.shader_cache.set(fragment_shader_path, fragment_shader_module);
|
||||
if self.shader_cache.get(fragment_shader_path).is_none() {
|
||||
let fragment_shader_module = compile_from_glsl(&self.device, fragment_shader_path, glsl_to_spirv::ShaderType::Fragment).unwrap();
|
||||
self.shader_cache.set(fragment_shader_path, fragment_shader_module);
|
||||
}
|
||||
|
||||
// Get the shader pair
|
||||
let vertex_shader = self.shader_cache.get(vertex_shader_path).unwrap();
|
||||
|
@ -125,14 +127,18 @@ impl Application {
|
|||
|
||||
// Construct a pipeline from the shader pair
|
||||
let pipeline_name = "example";
|
||||
let pipeline = Pipeline::new(&self.device, vertex_shader, fragment_shader);
|
||||
self.pipeline_cache.set(pipeline_name, pipeline);
|
||||
if self.pipeline_cache.get(pipeline_name).is_none() {
|
||||
let pipeline = Pipeline::new(&self.device, vertex_shader, fragment_shader);
|
||||
self.pipeline_cache.set(pipeline_name, pipeline);
|
||||
}
|
||||
let example_pipeline = self.pipeline_cache.get(pipeline_name).unwrap();
|
||||
|
||||
// Load a texture from the image file
|
||||
let texture_path = "textures/grid.png";
|
||||
let texture = Texture::from_filepath(&self.device, &mut self.queue, texture_path).unwrap();
|
||||
self.texture_cache.set(texture_path, texture);
|
||||
if self.texture_cache.get(texture_path).is_none() {
|
||||
let texture = Texture::from_filepath(&self.device, &mut self.queue, texture_path).unwrap();
|
||||
self.texture_cache.set(texture_path, texture);
|
||||
}
|
||||
let grid_texture = self.texture_cache.get(texture_path).unwrap();
|
||||
|
||||
// Create a BindGroup that holds a new TextureView
|
||||
|
@ -156,17 +162,19 @@ impl Application {
|
|||
self.draw_command_queue.push_back(draw_command);
|
||||
}
|
||||
|
||||
// Initializes the event loop for rendering and event handling
|
||||
pub fn begin_lifecycle(mut self, event_loop: EventLoop<()>, window: Window) {
|
||||
event_loop.run(move |event, _, control_flow| self.main_event_loop(event, control_flow, &window));
|
||||
}
|
||||
|
||||
// Called every time by the event loop
|
||||
pub fn main_event_loop<T>(&mut self, event: Event<'_, T>, control_flow: &mut ControlFlow, window: &Window) {
|
||||
// Wait for the next event to cause a subsequent event loop run, instead of looping instantly as a game would need
|
||||
*control_flow = ControlFlow::Wait;
|
||||
|
||||
match event {
|
||||
// Handle all window events (like input and resize) in sequence
|
||||
Event::WindowEvent { window_id, ref event } if window_id == window.id() => self.window_event(event, control_flow),
|
||||
Event::WindowEvent { window_id, ref event } if window_id == window.id() => window_events::window_event(self, control_flow, event),
|
||||
// Handle raw hardware-related events not related to a window
|
||||
Event::DeviceEvent { .. } => (),
|
||||
// Handle custom-dispatched events
|
||||
|
@ -185,54 +193,10 @@ impl Application {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn window_event(&mut self, event: &WindowEvent, control_flow: &mut ControlFlow) {
|
||||
match event {
|
||||
WindowEvent::Resized(physical_size) => self.resize(*physical_size),
|
||||
WindowEvent::Moved(_) => (),
|
||||
WindowEvent::CloseRequested => self.quit(control_flow),
|
||||
WindowEvent::Destroyed => (),
|
||||
WindowEvent::DroppedFile(_) => (),
|
||||
WindowEvent::HoveredFile(_) => (),
|
||||
WindowEvent::HoveredFileCancelled => (),
|
||||
WindowEvent::ReceivedCharacter(_) => (),
|
||||
WindowEvent::Focused(_) => (),
|
||||
WindowEvent::KeyboardInput { input, .. } => self.keyboard_event(input, control_flow),
|
||||
WindowEvent::CursorMoved { .. } => (),
|
||||
WindowEvent::CursorEntered { .. } => (),
|
||||
WindowEvent::CursorLeft { .. } => (),
|
||||
WindowEvent::MouseWheel { .. } => (),
|
||||
WindowEvent::MouseInput { .. } => (),
|
||||
WindowEvent::TouchpadPressure { .. } => (),
|
||||
WindowEvent::AxisMotion { .. } => (),
|
||||
WindowEvent::Touch(_) => (),
|
||||
WindowEvent::ScaleFactorChanged { new_inner_size, .. } => self.resize(**new_inner_size),
|
||||
WindowEvent::ThemeChanged(_) => (),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn keyboard_event(&mut self, input: &KeyboardInput, control_flow: &mut ControlFlow) {
|
||||
match input {
|
||||
KeyboardInput { state: ElementState::Pressed, virtual_keycode: Some(VirtualKeyCode::Escape), .. } => self.quit(control_flow),
|
||||
KeyboardInput { state: ElementState::Pressed, virtual_keycode: Some(VirtualKeyCode::Space), .. } => self.example(),
|
||||
_ => *control_flow = ControlFlow::Wait,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn quit(&self, control_flow: &mut ControlFlow) {
|
||||
*control_flow = ControlFlow::Exit;
|
||||
}
|
||||
|
||||
pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
|
||||
self.swap_chain_descriptor.width = new_size.width;
|
||||
self.swap_chain_descriptor.height = new_size.height;
|
||||
|
||||
self.swap_chain = self.device.create_swap_chain(&self.surface, &self.swap_chain_descriptor);
|
||||
|
||||
// TODO: Mark root of GUI as dirty to force redraw of everything
|
||||
}
|
||||
|
||||
// Traverse dirty GUI elements and turn GUI changes into draw commands added to the render pipeline queue
|
||||
pub fn redraw_gui(&mut self, window: &Window) {
|
||||
self.example();
|
||||
|
||||
// If any draw commands were actually added, ask the window to dispatch a redraw event
|
||||
if !self.draw_command_queue.is_empty() {
|
||||
window.request_redraw();
|
||||
|
|
|
@ -7,6 +7,7 @@ mod resource_cache;
|
|||
mod shader_stage;
|
||||
mod draw_command;
|
||||
mod gui_tree;
|
||||
mod window_events;
|
||||
|
||||
use application::Application;
|
||||
use winit::event_loop::EventLoop;
|
||||
|
@ -20,11 +21,7 @@ fn main() {
|
|||
let window = WindowBuilder::new().with_title("Graphite").build(&event_loop).unwrap();
|
||||
|
||||
// Initialize the render pipeline
|
||||
let mut app = Application::new(&window);
|
||||
app.example();
|
||||
|
||||
// State managers for render pipeline and program logic
|
||||
// let app_render_state = RenderState::new(&mut app);
|
||||
let app = Application::new(&window);
|
||||
|
||||
// Begin the application lifecycle
|
||||
app.begin_lifecycle(event_loop, window);
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::mem;
|
||||
|
||||
pub struct Pipeline {
|
||||
pub bind_group_layout: wgpu::BindGroupLayout,
|
||||
pub render_pipeline: wgpu::RenderPipeline,
|
||||
|
@ -58,7 +60,7 @@ impl Pipeline {
|
|||
vertex_state: wgpu::VertexStateDescriptor {
|
||||
index_format: wgpu::IndexFormat::Uint16,
|
||||
vertex_buffers: &[wgpu::VertexBufferDescriptor {
|
||||
stride: std::mem::size_of::<[f32; 2]>() as wgpu::BufferAddress,
|
||||
stride: mem::size_of::<[f32; 2]>() as wgpu::BufferAddress,
|
||||
step_mode: wgpu::InputStepMode::Vertex,
|
||||
attributes: &[wgpu::VertexAttributeDescriptor {
|
||||
offset: 0,
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
// use super::texture::Texture;
|
||||
// use super::application::Application;
|
||||
|
||||
// use std::collections::HashMap;
|
||||
|
||||
// pub struct RenderState {
|
||||
// pub render_pipeline: wgpu::RenderPipeline,
|
||||
// pub vertex_buffer: wgpu::Buffer,
|
||||
// pub index_buffer: wgpu::Buffer,
|
||||
// pub num_indices: u32,
|
||||
// pub texture: Texture,
|
||||
// pub texture_bind_group: wgpu::BindGroup,
|
||||
// }
|
||||
|
||||
// impl RenderState {
|
||||
// pub fn new(application: &mut Application) -> Self {
|
||||
|
||||
|
||||
// Self {
|
||||
// vertex_buffer,
|
||||
// index_buffer,
|
||||
// num_indices,
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
|
@ -1,5 +1,8 @@
|
|||
pub fn compile_from_glsl(device: &wgpu::Device, path: &str, shader_type: glsl_to_spirv::ShaderType) -> std::io::Result<wgpu::ShaderModule> {
|
||||
let source = std::fs::read_to_string(path)?;
|
||||
use std::fs;
|
||||
use std::io;
|
||||
|
||||
pub fn compile_from_glsl(device: &wgpu::Device, path: &str, shader_type: glsl_to_spirv::ShaderType) -> io::Result<wgpu::ShaderModule> {
|
||||
let source = fs::read_to_string(path)?;
|
||||
let spirv = match glsl_to_spirv::compile(&source[..], shader_type) {
|
||||
Ok(spirv_output) => spirv_output,
|
||||
Err(message) => {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use std::fs;
|
||||
use image::GenericImageView;
|
||||
|
||||
pub struct Texture {
|
||||
|
@ -9,7 +10,7 @@ pub struct Texture {
|
|||
impl Texture {
|
||||
pub fn from_filepath(device: &wgpu::Device, queue: &mut wgpu::Queue, path: &str) -> Result<Self, failure::Error> {
|
||||
// Read the raw bytes from the specified file
|
||||
let bytes = std::fs::read(path)?;
|
||||
let bytes = fs::read(path)?;
|
||||
|
||||
// Construct and return a Texture from the bytes
|
||||
Texture::from_bytes(device, queue, &bytes[..])
|
||||
|
|
49
src/window_events.rs
Normal file
49
src/window_events.rs
Normal file
|
@ -0,0 +1,49 @@
|
|||
use super::application::Application;
|
||||
use winit::event::*;
|
||||
use winit::event_loop::ControlFlow;
|
||||
|
||||
pub fn window_event(application: &mut Application, control_flow: &mut ControlFlow, event: &WindowEvent) {
|
||||
match event {
|
||||
WindowEvent::Resized(physical_size) => resize(application, *physical_size),
|
||||
WindowEvent::Moved(_) => (),
|
||||
WindowEvent::CloseRequested => quit(control_flow),
|
||||
WindowEvent::Destroyed => (),
|
||||
WindowEvent::DroppedFile(_) => (),
|
||||
WindowEvent::HoveredFile(_) => (),
|
||||
WindowEvent::HoveredFileCancelled => (),
|
||||
WindowEvent::ReceivedCharacter(_) => (),
|
||||
WindowEvent::Focused(_) => (),
|
||||
WindowEvent::KeyboardInput { input, .. } => keyboard_event(application, control_flow, input),
|
||||
WindowEvent::CursorMoved { .. } => (),
|
||||
WindowEvent::CursorEntered { .. } => (),
|
||||
WindowEvent::CursorLeft { .. } => (),
|
||||
WindowEvent::MouseWheel { .. } => (),
|
||||
WindowEvent::MouseInput { .. } => (),
|
||||
WindowEvent::TouchpadPressure { .. } => (),
|
||||
WindowEvent::AxisMotion { .. } => (),
|
||||
WindowEvent::Touch(_) => (),
|
||||
WindowEvent::ScaleFactorChanged { new_inner_size, .. } => resize(application, **new_inner_size),
|
||||
WindowEvent::ThemeChanged(_) => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn keyboard_event(application: &mut Application, control_flow: &mut ControlFlow, input: &KeyboardInput) {
|
||||
match input {
|
||||
KeyboardInput { state: ElementState::Pressed, virtual_keycode: Some(VirtualKeyCode::Escape), .. } => quit(control_flow),
|
||||
KeyboardInput { state: ElementState::Pressed, virtual_keycode: Some(VirtualKeyCode::Space), .. } => application.example(),
|
||||
_ => *control_flow = ControlFlow::Wait,
|
||||
}
|
||||
}
|
||||
|
||||
fn quit(control_flow: &mut ControlFlow) {
|
||||
*control_flow = ControlFlow::Exit;
|
||||
}
|
||||
|
||||
fn resize(application: &mut Application, new_size: winit::dpi::PhysicalSize<u32>) {
|
||||
application.swap_chain_descriptor.width = new_size.width;
|
||||
application.swap_chain_descriptor.height = new_size.height;
|
||||
|
||||
application.swap_chain = application.device.create_swap_chain(&application.surface, &application.swap_chain_descriptor);
|
||||
|
||||
// TODO: Mark root of GUI as dirty to force redraw of everything
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue