use super::*; use crate::viewport::ViewportInfo; 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_info: ViewportInfo, } impl DebugPass { pub fn new( device: Arc, layouts: Arc, target_info: ViewportInfo, ) -> Self { // TODO hook into ShaderStore system let shader = device.create_shader_module(&wgpu::include_wgsl!("debug_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_info.output_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: Some(wgpu::DepthStencilState { format: target_info.depth_format, depth_write_enabled: false, depth_compare: wgpu::CompareFunction::Less, stencil: Default::default(), bias: Default::default(), }), multisample: wgpu::MultisampleState { count: 1, mask: !0, alpha_to_coverage_enabled: false, }, multiview: None, }); Self { device, pipeline, target_info, } } } 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_info.output_format], depth_stencil: Some(wgpu::RenderBundleDepthStencil { format: self.target_info.depth_format, depth_read_only: false, // TODO optimize? stencil_read_only: true, }), 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())) } }