diff --git a/editor/src/lib.rs b/editor/src/lib.rs index fe8de3aa7b..b16c203ab0 100644 --- a/editor/src/lib.rs +++ b/editor/src/lib.rs @@ -11,12 +11,10 @@ use crate::buffer::create_rect_buffers; use crate::text::{build_glyph_brush, Text}; use crate::vertex::Vertex; -use cgmath::Ortho; +use ortho::{init_ortho, update_ortho_buffer, OrthoResources}; use std::error::Error; use std::io; use std::path::Path; -use wgpu::util::DeviceExt; -use wgpu::{BindGroup, BindGroupLayoutDescriptor, BindGroupLayoutEntry, Buffer, ShaderStage}; use winit::event; use winit::event::{Event, ModifiersState}; use winit::event_loop::ControlFlow; @@ -25,6 +23,7 @@ pub mod ast; mod buffer; pub mod file; mod keyboard_input; +mod ortho; pub mod pool; mod rect; pub mod text; @@ -41,31 +40,6 @@ pub fn launch(_filepaths: &[&Path]) -> io::Result<()> { Ok(()) } -#[repr(C)] -#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] -struct Uniforms { - // We can't use cgmath with bytemuck directly so we'll have - // to convert the Matrix4 into a 4x4 f32 array - ortho: [[f32; 4]; 4], -} - -impl Uniforms { - fn new(w: u32, h: u32) -> Self { - let ortho: cgmath::Matrix4 = Ortho:: { - left: 0.0, - right: w as f32, - bottom: h as f32, - top: 0.0, - near: -1.0, - far: 1.0, - } - .into(); - Self { - ortho: ortho.into(), - } - } -} - fn run_event_loop() -> Result<(), Box> { env_logger::init(); @@ -123,8 +97,7 @@ fn run_event_loop() -> Result<(), Box> { let mut swap_chain = gpu_device.create_swap_chain(&surface, &swap_chain_descr); - let (rect_pipeline, ortho_bind_group, ortho_buffer) = - make_rect_pipeline(&gpu_device, &swap_chain_descr); + let (rect_pipeline, ortho) = make_rect_pipeline(&gpu_device, &swap_chain_descr); let mut glyph_brush = build_glyph_brush(&gpu_device, render_format)?; @@ -169,33 +142,13 @@ fn run_event_loop() -> Result<(), Box> { }, ); - // update orthographic buffer according to new window size - let new_uniforms = Uniforms::new(size.width, size.height); - - let new_ortho_buffer = - gpu_device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some("Ortho uniform buffer"), - contents: bytemuck::cast_slice(&[new_uniforms]), - usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_SRC, - }); - - // get a command encoder for the current frame - let mut encoder = - gpu_device.create_command_encoder(&wgpu::CommandEncoderDescriptor { - label: Some("Resize"), - }); - - // overwrite the new buffer over the old one - encoder.copy_buffer_to_buffer( - &new_ortho_buffer, - 0, - &ortho_buffer, - 0, - (std::mem::size_of::() * vec![new_uniforms].as_slice().len()) - as wgpu::BufferAddress, + update_ortho_buffer( + size.width, + size.height, + &gpu_device, + &ortho.buffer, + &cmd_queue, ); - - cmd_queue.submit(Some(encoder.finish())); } //Received Character Event::WindowEvent { @@ -250,7 +203,7 @@ fn run_event_loop() -> Result<(), Box> { if rect_buffers.num_rects > 0 { render_pass.set_pipeline(&rect_pipeline); - render_pass.set_bind_group(0, &ortho_bind_group, &[]); + render_pass.set_bind_group(0, &ortho.bind_group, &[]); render_pass.set_vertex_buffer(0, rect_buffers.vertex_buffer.slice(..)); render_pass.set_index_buffer(rect_buffers.index_buffer.slice(..)); render_pass.draw_indexed(0..rect_buffers.num_rects, 0, 0..1); @@ -290,41 +243,11 @@ fn run_event_loop() -> Result<(), Box> { fn make_rect_pipeline( gpu_device: &wgpu::Device, swap_chain_descr: &wgpu::SwapChainDescriptor, -) -> (wgpu::RenderPipeline, BindGroup, Buffer) { - let uniforms = Uniforms::new(swap_chain_descr.width, swap_chain_descr.height); - - // orthographic projection is used to transfrom pixel coords to the coordinate system used by wgpu - let ortho_buffer = gpu_device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some("Ortho uniform buffer"), - contents: bytemuck::cast_slice(&[uniforms]), - usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, - }); - - // bind groups consist of extra resources that are provided to the shaders - let ortho_bind_group_layout = gpu_device.create_bind_group_layout(&BindGroupLayoutDescriptor { - entries: &[BindGroupLayoutEntry { - binding: 0, - visibility: ShaderStage::VERTEX, - ty: wgpu::BindingType::UniformBuffer { - dynamic: false, - min_binding_size: None, - }, - count: None, - }], - label: Some("Ortho bind group layout"), - }); - - let ortho_bind_group = gpu_device.create_bind_group(&wgpu::BindGroupDescriptor { - layout: &ortho_bind_group_layout, - entries: &[wgpu::BindGroupEntry { - binding: 0, - resource: wgpu::BindingResource::Buffer(ortho_buffer.slice(..)), - }], - label: Some("Ortho bind group"), - }); +) -> (wgpu::RenderPipeline, OrthoResources) { + let ortho = init_ortho(swap_chain_descr.width, swap_chain_descr.height, gpu_device); let pipeline_layout = gpu_device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - bind_group_layouts: &[&ortho_bind_group_layout], + bind_group_layouts: &[&ortho.bind_group_layout], push_constant_ranges: &[], label: Some("Rectangle pipeline layout"), }); @@ -337,7 +260,7 @@ fn make_rect_pipeline( wgpu::include_spirv!("shaders/rect.frag.spv"), ); - (pipeline, ortho_bind_group, ortho_buffer) + (pipeline, ortho) } fn create_render_pipeline( diff --git a/editor/src/ortho.rs b/editor/src/ortho.rs new file mode 100644 index 0000000000..8acbe2a66e --- /dev/null +++ b/editor/src/ortho.rs @@ -0,0 +1,116 @@ +use cgmath::{Matrix4, Ortho}; +use wgpu::util::DeviceExt; +use wgpu::{ + BindGroup, BindGroupLayout, BindGroupLayoutDescriptor, BindGroupLayoutEntry, Buffer, + ShaderStage, +}; + +// orthographic projection is used to transfrom pixel coords to the coordinate system used by wgpu + +#[repr(C)] +#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] +struct Uniforms { + // We can't use cgmath with bytemuck directly so we'll have + // to convert the Matrix4 into a 4x4 f32 array + ortho: [[f32; 4]; 4], +} + +impl Uniforms { + fn new(w: u32, h: u32) -> Self { + let ortho: Matrix4 = Ortho:: { + left: 0.0, + right: w as f32, + bottom: h as f32, + top: 0.0, + near: -1.0, + far: 1.0, + } + .into(); + Self { + ortho: ortho.into(), + } + } +} + +// update orthographic buffer according to new window size +pub fn update_ortho_buffer( + inner_width: u32, + inner_height: u32, + gpu_device: &wgpu::Device, + ortho_buffer: &Buffer, + cmd_queue: &wgpu::Queue, +) { + let new_uniforms = Uniforms::new(inner_width, inner_height); + + let new_ortho_buffer = gpu_device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("Ortho uniform buffer"), + contents: bytemuck::cast_slice(&[new_uniforms]), + usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_SRC, + }); + + // get a command encoder for the current frame + let mut encoder = gpu_device.create_command_encoder(&wgpu::CommandEncoderDescriptor { + label: Some("Resize"), + }); + + // overwrite the new buffer over the old one + encoder.copy_buffer_to_buffer( + &new_ortho_buffer, + 0, + ortho_buffer, + 0, + (std::mem::size_of::() * vec![new_uniforms].as_slice().len()) + as wgpu::BufferAddress, + ); + + cmd_queue.submit(Some(encoder.finish())); +} + +pub struct OrthoResources { + pub buffer: Buffer, + pub bind_group_layout: BindGroupLayout, + pub bind_group: BindGroup, +} + +pub fn init_ortho( + inner_width: u32, + inner_height: u32, + gpu_device: &wgpu::Device, +) -> OrthoResources { + let uniforms = Uniforms::new(inner_width, inner_height); + + let ortho_buffer = gpu_device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("Ortho uniform buffer"), + contents: bytemuck::cast_slice(&[uniforms]), + usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, + }); + + // bind groups consist of extra resources that are provided to the shaders + let ortho_bind_group_layout = gpu_device.create_bind_group_layout(&BindGroupLayoutDescriptor { + entries: &[BindGroupLayoutEntry { + binding: 0, + visibility: ShaderStage::VERTEX, + ty: wgpu::BindingType::UniformBuffer { + dynamic: false, + min_binding_size: None, + }, + count: None, + }], + label: Some("Ortho bind group layout"), + }); + + let ortho_bind_group = gpu_device.create_bind_group(&wgpu::BindGroupDescriptor { + layout: &ortho_bind_group_layout, + entries: &[wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::Buffer(ortho_buffer.slice(..)), + }], + label: Some("Ortho bind group"), + }); + + OrthoResources { + buffer: ortho_buffer, + bind_group_layout: ortho_bind_group_layout, + bind_group: ortho_bind_group, + } +}