diff --git a/src/main.rs b/src/main.rs index 1649c2d..eeb1010 100644 --- a/src/main.rs +++ b/src/main.rs @@ -79,8 +79,10 @@ fn main() { let layouts = renderer.get_layouts(); let mesh_pass = pass::mesh::MeshPass::new(device.to_owned(), layouts.to_owned(), viewport.config.format); + let debug_pass = pass::debug::DebugPass::new(device.to_owned(), layouts.to_owned(), viewport.config.format); renderer.add_pass(mesh_pass); + renderer.add_pass(debug_pass); event_loop.run(move |event, _, control_flow| match event { Event::RedrawRequested(_) => { diff --git a/src/pass.rs b/src/pass.rs index e5c438a..6e881c1 100644 --- a/src/pass.rs +++ b/src/pass.rs @@ -3,6 +3,7 @@ use crate::phase::Phase; use std::sync::Arc; +pub mod debug; pub mod mesh; /// Viewport data shared by all passes, once the [ViewportPhase] group is diff --git a/src/pass/debug.rs b/src/pass/debug.rs new file mode 100644 index 0000000..fc5b037 --- /dev/null +++ b/src/pass/debug.rs @@ -0,0 +1,172 @@ +use super::*; +use crate::RenderLayouts; + +#[repr(C)] +#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] +pub struct Vertex { + pub position: [f32; 3], + pub color: [f32; 3], +} + +const VERTEX_ATTRS: &[wgpu::VertexAttribute] = + &wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3]; + +impl Vertex { + pub fn desc() -> wgpu::VertexBufferLayout<'static> { + wgpu::VertexBufferLayout { + array_stride: std::mem::size_of::() as wgpu::BufferAddress, + step_mode: wgpu::VertexStepMode::Vertex, + attributes: VERTEX_ATTRS, + } + } +} + +pub type Index = u32; + +pub struct FrameData { + vertex_capacity: usize, + vertices: wgpu::Buffer, + index_capacity: usize, + indices: wgpu::Buffer, + index_num: usize, +} + +pub struct DebugPass { + device: Arc, + pipeline: wgpu::RenderPipeline, + target_format: wgpu::TextureFormat, +} + +impl DebugPass { + pub fn new( + device: Arc, + layouts: Arc, + target_format: wgpu::TextureFormat, + ) -> Self { + let shader = device.create_shader_module(&wgpu::include_wgsl!("mesh_shader.wgsl")); + + let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("DebugPass Pipeline Layout"), + bind_group_layouts: &[&layouts.bind_viewport], + push_constant_ranges: &[], + }); + + let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("DebugPass Pipeline"), + layout: Some(&pipeline_layout), + vertex: wgpu::VertexState { + module: &shader, + entry_point: "vs_main", + buffers: &[Vertex::desc()], + }, + fragment: Some(wgpu::FragmentState { + module: &shader, + entry_point: "fs_main", + targets: &[wgpu::ColorTargetState { + format: target_format, + blend: Some(wgpu::BlendState::REPLACE), + write_mask: wgpu::ColorWrites::ALL, + }], + }), + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::LineList, + strip_index_format: None, + front_face: wgpu::FrontFace::Ccw, + cull_mode: None, + polygon_mode: wgpu::PolygonMode::Fill, + unclipped_depth: false, + conservative: false, + }, + depth_stencil: None, + multisample: wgpu::MultisampleState { + count: 1, + mask: !0, + alpha_to_coverage_enabled: false, + }, + multiview: None, + }); + + Self { + device, + pipeline, + target_format, + } + } +} + +impl RenderPass for DebugPass { + type FrameData = FrameData; + + fn create_frame_data(&self) -> FrameData { + let vertex_capacity = 1024 * 1024; // TODO resizable buffers + let vertices = self.device.create_buffer(&wgpu::BufferDescriptor { + label: Some("DebugPass Vertex Buffer"), + size: (vertex_capacity * std::mem::size_of::()) as wgpu::BufferAddress, + mapped_at_creation: false, + usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST, + }); + + let index_capacity = 1024 * 1024; // TODO resizable buffers + let indices = self.device.create_buffer(&wgpu::BufferDescriptor { + label: Some("DebugPass Index Buffer"), + size: (index_capacity * std::mem::size_of::()) as wgpu::BufferAddress, + mapped_at_creation: false, + usage: wgpu::BufferUsages::INDEX | wgpu::BufferUsages::COPY_DST, + }); + + let index_num = 0; + + FrameData { + vertex_capacity, + vertices, + index_capacity, + indices, + index_num, + } + } + + fn begin_frame(&self, data: &mut FrameData, phases: &mut Vec, queue: &wgpu::Queue) { + phases.push(Phase::Overlay); + + let vertices = &[ + Vertex { + position: [0.0, 0.0, -1.0], + color: [1.0, 0.0, 0.0], + }, + Vertex { + position: [0.0, 0.0, 1.0], + color: [0.0, 0.0, 1.0], + }, + ]; + queue.write_buffer(&data.vertices, 0, bytemuck::cast_slice(vertices)); + + let indices = &[0u32, 1u32]; + queue.write_buffer(&data.indices, 0, bytemuck::cast_slice(indices)); + + data.index_num = 2; + } + + fn record_render(&self, data: PhaseData<&FrameData>) -> Option { + println!("DebugPass::record_render(phase: {:?})", data.phase); + + let mut cmds = + self.device + .create_render_bundle_encoder(&wgpu::RenderBundleEncoderDescriptor { + label: Some("DebugPass Render Bundle"), + color_formats: &[self.target_format], + depth_stencil: None, + sample_count: 1, + multiview: None, + }); + + cmds.set_pipeline(&self.pipeline); + cmds.set_bind_group(0, data.bind_viewport, &[]); + cmds.set_vertex_buffer(0, data.frame_data.vertices.slice(..)); + cmds.set_index_buffer(data.frame_data.indices.slice(..), wgpu::IndexFormat::Uint32); + + let index_range = 0..(data.frame_data.index_num as u32); + cmds.draw_indexed(index_range, 0, 0..1); + + Some(cmds.finish(&wgpu::RenderBundleDescriptor::default())) + } +}