From f438f0b920a75bd3ffb093d2750e2ac99569cafb Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Mon, 31 May 2021 22:19:51 -0400 Subject: [PATCH] [rs] Bunnymark example --- wgpu/examples/bunnymark/icon.png | Bin 0 -> 15713 bytes wgpu/examples/bunnymark/main.rs | 359 ++++++++++++++++++++++++++++ wgpu/examples/bunnymark/shader.wgsl | 43 ++++ 3 files changed, 402 insertions(+) create mode 100644 wgpu/examples/bunnymark/icon.png create mode 100644 wgpu/examples/bunnymark/main.rs create mode 100644 wgpu/examples/bunnymark/shader.wgsl diff --git a/wgpu/examples/bunnymark/icon.png b/wgpu/examples/bunnymark/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..5e72defd21325e252a4ecce54b5858c5c55882a0 GIT binary patch literal 15713 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, + local_buffer: wgpu::Buffer, + extent: [u32; 2], +} + +impl framework::Example for Example { + /// constructs initial instance of Example struct + fn init( + sc_desc: &wgpu::SwapChainDescriptor, + _adapter: &wgpu::Adapter, + device: &wgpu::Device, + queue: &wgpu::Queue, + ) -> Self { + let shader = device.create_shader_module(&wgpu::ShaderModuleDescriptor { + label: None, + source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("shader.wgsl"))), + flags: wgpu::ShaderFlags::all(), + }); + + let global_bind_group_layout = + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: wgpu::BufferSize::new(mem::size_of::() as _), + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 2, + visibility: wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { + filtering: true, + comparison: false, + }, + count: None, + }, + ], + label: None, + }); + let local_bind_group_layout = + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::VERTEX, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: true, + min_binding_size: wgpu::BufferSize::new(mem::size_of::() as _), + }, + count: None, + }], + label: None, + }); + let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: None, + bind_group_layouts: &[&global_bind_group_layout, &local_bind_group_layout], + push_constant_ranges: &[], + }); + + let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: None, + layout: Some(&pipeline_layout), + vertex: wgpu::VertexState { + module: &shader, + entry_point: "vs_main", + buffers: &[], + }, + fragment: Some(wgpu::FragmentState { + module: &shader, + entry_point: "fs_main", + targets: &[wgpu::ColorTargetState { + format: sc_desc.format, + blend: Some(wgpu::BlendState::ALPHA_BLENDING), + write_mask: wgpu::ColorWrite::default(), + }], + }), + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleStrip, + ..wgpu::PrimitiveState::default() + }, + depth_stencil: None, + multisample: wgpu::MultisampleState::default(), + }); + + let texture = { + let img_data = include_bytes!("icon.png"); + let decoder = png::Decoder::new(std::io::Cursor::new(img_data)); + let (info, mut reader) = decoder.read_info().unwrap(); + let mut buf = vec![0; info.buffer_size()]; + reader.next_frame(&mut buf).unwrap(); + + let size = wgpu::Extent3d { + width: info.width, + height: info.height, + depth_or_array_layers: 1, + }; + let texture = device.create_texture(&wgpu::TextureDescriptor { + label: None, + size, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Rgba8UnormSrgb, + usage: wgpu::TextureUsage::COPY_DST | wgpu::TextureUsage::SAMPLED, + }); + queue.write_texture( + wgpu::ImageCopyTexture { + texture: &texture, + mip_level: 0, + origin: wgpu::Origin3d::ZERO, + }, + &buf, + wgpu::ImageDataLayout { + offset: 0, + bytes_per_row: std::num::NonZeroU32::new(info.width * 4), + rows_per_image: None, + }, + size, + ); + texture + }; + + let sampler = device.create_sampler(&wgpu::SamplerDescriptor { + label: None, + address_mode_u: wgpu::AddressMode::ClampToEdge, + address_mode_v: wgpu::AddressMode::ClampToEdge, + address_mode_w: wgpu::AddressMode::ClampToEdge, + mag_filter: wgpu::FilterMode::Linear, + min_filter: wgpu::FilterMode::Nearest, + mipmap_filter: wgpu::FilterMode::Nearest, + ..Default::default() + }); + + let globals = Globals { + mvp: cgmath::ortho( + 0.0, + sc_desc.width as f32, + 0.0, + sc_desc.height as f32, + -1.0, + 1.0, + ) + .into(), + size: [BUNNY_SIZE; 2], + pad: [0.0; 2], + }; + let global_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("global"), + contents: bytemuck::bytes_of(&globals), + usage: wgpu::BufferUsage::COPY_DST | wgpu::BufferUsage::UNIFORM, + }); + let local_buffer = device.create_buffer(&wgpu::BufferDescriptor { + label: Some("local"), + size: (MAX_BUNNIES as wgpu::BufferAddress) * wgpu::BIND_BUFFER_ALIGNMENT, + usage: wgpu::BufferUsage::COPY_DST | wgpu::BufferUsage::UNIFORM, + mapped_at_creation: false, + }); + + let view = texture.create_view(&wgpu::TextureViewDescriptor::default()); + let global_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + layout: &global_bind_group_layout, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: global_buffer.as_entire_binding(), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::TextureView(&view), + }, + wgpu::BindGroupEntry { + binding: 2, + resource: wgpu::BindingResource::Sampler(&sampler), + }, + ], + label: None, + }); + let local_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + layout: &local_bind_group_layout, + entries: &[wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding { + buffer: &local_buffer, + offset: 0, + size: wgpu::BufferSize::new(mem::size_of::() as _), + }), + }], + label: None, + }); + + Example { + pipeline, + global_group, + local_group, + bunnies: Vec::new(), + local_buffer, + extent: [sc_desc.width, sc_desc.height], + } + } + + /// update is called for any WindowEvent not handled by the framework + fn update(&mut self, event: winit::event::WindowEvent) { + if let winit::event::WindowEvent::KeyboardInput { + input: + winit::event::KeyboardInput { + virtual_keycode: Some(winit::event::VirtualKeyCode::Space), + state: winit::event::ElementState::Pressed, + .. + }, + .. + } = event + { + let spawn_count = 64 + self.bunnies.len() / 2; + let color = rand::random::(); + println!( + "Spawning {} bunnies, total at {}", + spawn_count, + self.bunnies.len() + spawn_count + ); + for _ in 0..spawn_count { + let speed = rand::random::() * MAX_VELOCITY - (MAX_VELOCITY * 0.5); + self.bunnies.push(Locals { + position: [0.0, 0.5 * (self.extent[1] as f32)], + velocity: [speed, 0.0], + color, + _pad: 0, + }); + } + } + } + + /// resize is called on WindowEvent::Resized events + fn resize( + &mut self, + _sc_desc: &wgpu::SwapChainDescriptor, + _device: &wgpu::Device, + _queue: &wgpu::Queue, + ) { + //empty + } + + /// render is called each frame, dispatching compute groups proportional + /// a TriangleList draw call for all NUM_PARTICLES at 3 vertices each + fn render( + &mut self, + frame: &wgpu::SwapChainTexture, + device: &wgpu::Device, + queue: &wgpu::Queue, + _spawner: &framework::Spawner, + ) { + let delta = 0.01; + for bunny in self.bunnies.iter_mut() { + bunny.position[0] += bunny.velocity[0] * delta; + bunny.position[1] += bunny.velocity[1] * delta; + bunny.velocity[1] += GRAVITY * delta; + if (bunny.velocity[0] > 0.0 + && bunny.position[0] + 0.5 * BUNNY_SIZE > self.extent[0] as f32) + || (bunny.velocity[0] < 0.0 && bunny.position[0] - 0.5 * BUNNY_SIZE < 0.0) + { + bunny.velocity[0] *= -1.0; + } + if bunny.velocity[1] < 0.0 && bunny.position[1] < 0.5 * BUNNY_SIZE { + bunny.velocity[1] *= -1.0; + } + } + + queue.write_buffer(&self.local_buffer, 0, unsafe { + std::slice::from_raw_parts( + self.bunnies.as_ptr() as *const u8, + self.bunnies.len() * wgpu::BIND_BUFFER_ALIGNMENT as usize, + ) + }); + + let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor::default()); + { + let clear_color = wgpu::Color { + r: 0.1, + g: 0.2, + b: 0.3, + a: 1.0, + }; + let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: None, + color_attachments: &[wgpu::RenderPassColorAttachment { + view: &frame.view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(clear_color), + store: true, + }, + }], + depth_stencil_attachment: None, + }); + rpass.set_pipeline(&self.pipeline); + rpass.set_bind_group(0, &self.global_group, &[]); + for i in 0..self.bunnies.len() { + let offset = (i as wgpu::DynamicOffset) + * (wgpu::BIND_BUFFER_ALIGNMENT as wgpu::DynamicOffset); + rpass.set_bind_group(1, &self.local_group, &[offset]); + rpass.draw(0..4, 0..1); + } + } + + queue.submit(Some(encoder.finish())); + } +} + +fn main() { + framework::run::("bunnymark"); +} diff --git a/wgpu/examples/bunnymark/shader.wgsl b/wgpu/examples/bunnymark/shader.wgsl new file mode 100644 index 0000000000..b8639d1ca3 --- /dev/null +++ b/wgpu/examples/bunnymark/shader.wgsl @@ -0,0 +1,43 @@ +[[block]] +struct Globals { + mvp: mat4x4; + size: vec2; +}; + +[[block]] +struct Locals { + position: vec2; + velocity: vec2; + color: u32; +}; + +[[group(0), binding(0)]] +var globals: Globals; + +[[group(1), binding(0)]] +var locals: Locals; + +struct VertexOutput { + [[builtin(position)]] position: vec4; + [[location(0)]] tex_coords: vec2; + [[location(1)]] color: vec4; +}; + +[[stage(vertex)]] +fn vs_main([[builtin(vertex_index)]] vi: u32) -> VertexOutput { + let tc = vec2(f32(vi & 1u), 0.5 * f32(vi & 2u)); + let offset = vec2(tc.x * globals.size.x, tc.y * globals.size.y); + let pos = globals.mvp * vec4(locals.position + offset, 0.0, 1.0); + let color = vec4((vec4(locals.color) >> vec4(0u, 8u, 16u, 24u)) & vec4(255u)) / 255.0; + return VertexOutput(pos, tc, color); +} + +[[group(0), binding(1)]] +var texture: texture_2d; +[[group(0), binding(2)]] +var sampler: sampler; + +[[stage(fragment)]] +fn fs_main(in: VertexOutput) -> [[location(0)]] vec4 { + return in.color * textureSampleLevel(texture, sampler, in.tex_coords, 0.0); +}