From 09c7ab16700a5f8ccc972f29e3c85757d174573d Mon Sep 17 00:00:00 2001 From: Andrew Thomas Date: Sun, 12 May 2024 12:32:54 -0700 Subject: [PATCH 1/9] ok so this isn't working but, getting somewhere i guess --- examples/render_wgpu/Cargo.toml | 11 ++ examples/render_wgpu/src/main.rs | 148 +++++++++++++++++++++++++++ examples/render_wgpu/src/shader.wgsl | 24 +++++ 3 files changed, 183 insertions(+) create mode 100644 examples/render_wgpu/Cargo.toml create mode 100644 examples/render_wgpu/src/main.rs create mode 100644 examples/render_wgpu/src/shader.wgsl diff --git a/examples/render_wgpu/Cargo.toml b/examples/render_wgpu/Cargo.toml new file mode 100644 index 0000000..2705a61 --- /dev/null +++ b/examples/render_wgpu/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "render_wgpu" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +wgpu = "0.18" +baseview = {path = "../.."} +pollster = "0.3.0" diff --git a/examples/render_wgpu/src/main.rs b/examples/render_wgpu/src/main.rs new file mode 100644 index 0000000..bab6006 --- /dev/null +++ b/examples/render_wgpu/src/main.rs @@ -0,0 +1,148 @@ +use baseview::{Size, Window, WindowHandler, WindowOpenOptions}; +use wgpu::{Device, RenderPipeline, Surface}; + +struct WgpuExample { + pipeline: RenderPipeline, + surface: Surface, + device: Device, +} + +impl<'a> WgpuExample { + pub async fn new(window: &mut Window<'a>) -> Self { + let instance = wgpu::Instance::new(wgpu::InstanceDescriptor::default()); + let surface = unsafe { instance.create_surface(window) }.unwrap(); + let adapter = instance + .request_adapter(&wgpu::RequestAdapterOptions { + power_preference: wgpu::PowerPreference::default(), + compatible_surface: Some(&surface), + force_fallback_adapter: false, + }) + .await + .unwrap(); + let (device, _queue) = adapter + .request_device( + &wgpu::DeviceDescriptor { + features: wgpu::Features::empty(), + limits: wgpu::Limits::default(), + label: None, + }, + None, + ) + .await + .unwrap(); + + let surface_caps = surface.get_capabilities(&adapter); + let surface_format = surface_caps + .formats + .iter() + .copied() + .filter(|f| f.is_srgb()) + .next() + .unwrap_or(surface_caps.formats[0]); + let config = wgpu::SurfaceConfiguration { + usage: wgpu::TextureUsages::RENDER_ATTACHMENT, + format: surface_format, + width: 512, + height: 512, + present_mode: surface_caps.present_modes[0], + alpha_mode: surface_caps.alpha_modes[0], + view_formats: vec![], + }; + + let shader = device.create_shader_module(wgpu::include_wgsl!("shader.wgsl")); + + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Render Pipeline Layout"), + bind_group_layouts: &[], + push_constant_ranges: &[], + }); + + let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Render Pipeline"), + layout: Some(&render_pipeline_layout), + vertex: wgpu::VertexState { + module: &shader, + entry_point: "vs_main", // 1. + buffers: &[], // 2. + }, + fragment: Some(wgpu::FragmentState { + // 3. + module: &shader, + entry_point: "fs_main", + targets: &[Some(wgpu::ColorTargetState { + // 4. + format: config.format, + blend: Some(wgpu::BlendState::REPLACE), + write_mask: wgpu::ColorWrites::ALL, + })], + }), + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, // 1. + strip_index_format: None, + front_face: wgpu::FrontFace::Ccw, // 2. + cull_mode: Some(wgpu::Face::Back), + polygon_mode: wgpu::PolygonMode::Fill, + unclipped_depth: false, + conservative: false, + }, + depth_stencil: None, // 1. + multisample: wgpu::MultisampleState { + count: 1, // 2. + mask: !0, // 3. + alpha_to_coverage_enabled: false, // 4. + }, + multiview: None, + }); + + surface.configure(&device, &config); + + Self { pipeline, surface, device } + } +} + +impl WindowHandler for WgpuExample { + fn on_frame(&mut self, window: &mut baseview::Window) { + let output = self.surface.get_current_texture().unwrap(); + let view = output.texture.create_view(&wgpu::TextureViewDescriptor::default()); + + let mut encoder = self.device.create_command_encoder(&wgpu::CommandEncoderDescriptor { + label: Some("Render Encoder"), + }); + + let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some("Render Pass"), + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view: &view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color { r: 0.1, g: 0.2, b: 0.3, a: 1.0 }), + store: wgpu::StoreOp::Store, + }, + })], + depth_stencil_attachment: None, + occlusion_query_set: None, + timestamp_writes: None, + }); + + render_pass.set_pipeline(&self.pipeline); + render_pass.draw(0..3, 0..1); + } + fn on_event( + &mut self, window: &mut baseview::Window, event: baseview::Event, + ) -> baseview::EventStatus { + baseview::EventStatus::Captured + } +} + +fn main() { + let window_open_options = WindowOpenOptions { + title: "wgpu on baseview".into(), + size: Size::new(512.0, 512.0), + scale: baseview::WindowScalePolicy::SystemScaleFactor, + }; + + Window::open_blocking(window_open_options, |window| { + pollster::block_on(WgpuExample::new(window)) + }) +} diff --git a/examples/render_wgpu/src/shader.wgsl b/examples/render_wgpu/src/shader.wgsl new file mode 100644 index 0000000..7f0bb3a --- /dev/null +++ b/examples/render_wgpu/src/shader.wgsl @@ -0,0 +1,24 @@ +// Vertex shader + +struct VertexOutput { + @builtin(position) clip_position: vec4, +}; + +@vertex +fn vs_main( + @builtin(vertex_index) in_vertex_index: u32, +) -> VertexOutput { + var out: VertexOutput; + let x = f32(1 - i32(in_vertex_index)) * 0.5; + let y = f32(i32(in_vertex_index & 1u) * 2 - 1) * 0.5; + out.clip_position = vec4(x, y, 0.0, 1.0); + return out; +} + +// Fragment shader + +@fragment +fn fs_main(in: VertexOutput) -> @location(0) vec4 { + return vec4(0.3, 0.2, 0.1, 1.0); +} + From 47fd84e9dec6ccf5a028bb0327b33aa73e103f69 Mon Sep 17 00:00:00 2001 From: Andrew Thomas Date: Sun, 12 May 2024 12:34:07 -0700 Subject: [PATCH 2/9] ok getting somewhere --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 2d65e46..b4b1052 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,7 +42,7 @@ rtrb = "0.2" softbuffer = "0.3.4" [workspace] -members = ["examples/render_femtovg"] +members = ["examples/render_femtovg", "examples/render_wgpu"] [lints.clippy] missing-safety-doc = "allow" From 5cc2c1e511440485c7791b643a706a8c50e7b9b4 Mon Sep 17 00:00:00 2001 From: Andrew Thomas Date: Sun, 12 May 2024 12:51:22 -0700 Subject: [PATCH 3/9] ladies and gentlemen, we have a triangle --- examples/render_wgpu/Cargo.toml | 2 +- examples/render_wgpu/src/main.rs | 78 +++++++++++++++++--------------- 2 files changed, 42 insertions(+), 38 deletions(-) diff --git a/examples/render_wgpu/Cargo.toml b/examples/render_wgpu/Cargo.toml index 2705a61..08e3c5d 100644 --- a/examples/render_wgpu/Cargo.toml +++ b/examples/render_wgpu/Cargo.toml @@ -7,5 +7,5 @@ edition = "2021" [dependencies] wgpu = "0.18" -baseview = {path = "../.."} +baseview = {path = "../..", features = ["opengl"]} pollster = "0.3.0" diff --git a/examples/render_wgpu/src/main.rs b/examples/render_wgpu/src/main.rs index bab6006..2a45696 100644 --- a/examples/render_wgpu/src/main.rs +++ b/examples/render_wgpu/src/main.rs @@ -1,10 +1,13 @@ use baseview::{Size, Window, WindowHandler, WindowOpenOptions}; -use wgpu::{Device, RenderPipeline, Surface}; +use wgpu::{Device, Instance, Queue, RenderPipeline, Surface, SurfaceConfiguration}; struct WgpuExample { pipeline: RenderPipeline, - surface: Surface, device: Device, + config: SurfaceConfiguration, + instance: Instance, + surface: Surface, + queue: Queue, } impl<'a> WgpuExample { @@ -19,7 +22,7 @@ impl<'a> WgpuExample { }) .await .unwrap(); - let (device, _queue) = adapter + let (device, queue) = adapter .request_device( &wgpu::DeviceDescriptor { features: wgpu::Features::empty(), @@ -42,8 +45,9 @@ impl<'a> WgpuExample { let config = wgpu::SurfaceConfiguration { usage: wgpu::TextureUsages::RENDER_ATTACHMENT, format: surface_format, - width: 512, - height: 512, + // TODO this needs to be twice the window size for some reason + width: 1024, + height: 1024, present_mode: surface_caps.present_modes[0], alpha_mode: surface_caps.alpha_modes[0], view_formats: vec![], @@ -61,48 +65,42 @@ impl<'a> WgpuExample { let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { label: Some("Render Pipeline"), layout: Some(&render_pipeline_layout), - vertex: wgpu::VertexState { - module: &shader, - entry_point: "vs_main", // 1. - buffers: &[], // 2. - }, + vertex: wgpu::VertexState { module: &shader, entry_point: "vs_main", buffers: &[] }, fragment: Some(wgpu::FragmentState { - // 3. module: &shader, entry_point: "fs_main", targets: &[Some(wgpu::ColorTargetState { - // 4. format: config.format, blend: Some(wgpu::BlendState::REPLACE), write_mask: wgpu::ColorWrites::ALL, })], }), primitive: wgpu::PrimitiveState { - topology: wgpu::PrimitiveTopology::TriangleList, // 1. + topology: wgpu::PrimitiveTopology::TriangleList, strip_index_format: None, - front_face: wgpu::FrontFace::Ccw, // 2. + front_face: wgpu::FrontFace::Ccw, cull_mode: Some(wgpu::Face::Back), polygon_mode: wgpu::PolygonMode::Fill, unclipped_depth: false, conservative: false, }, - depth_stencil: None, // 1. + depth_stencil: None, multisample: wgpu::MultisampleState { - count: 1, // 2. - mask: !0, // 3. - alpha_to_coverage_enabled: false, // 4. + count: 1, + mask: !0, + alpha_to_coverage_enabled: false, }, multiview: None, }); surface.configure(&device, &config); - Self { pipeline, surface, device } + Self { pipeline, device, config, instance, surface, queue } } } impl WindowHandler for WgpuExample { - fn on_frame(&mut self, window: &mut baseview::Window) { + fn on_frame(&mut self, _window: &mut baseview::Window) { let output = self.surface.get_current_texture().unwrap(); let view = output.texture.create_view(&wgpu::TextureViewDescriptor::default()); @@ -110,26 +108,31 @@ impl WindowHandler for WgpuExample { label: Some("Render Encoder"), }); - let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - label: Some("Render Pass"), - color_attachments: &[Some(wgpu::RenderPassColorAttachment { - view: &view, - resolve_target: None, - ops: wgpu::Operations { - load: wgpu::LoadOp::Clear(wgpu::Color { r: 0.1, g: 0.2, b: 0.3, a: 1.0 }), - store: wgpu::StoreOp::Store, - }, - })], - depth_stencil_attachment: None, - occlusion_query_set: None, - timestamp_writes: None, - }); + { + let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some("Render Pass"), + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view: &view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color { r: 0.1, g: 0.2, b: 0.3, a: 1.0 }), + store: wgpu::StoreOp::Store, + }, + })], + depth_stencil_attachment: None, + occlusion_query_set: None, + timestamp_writes: None, + }); + + render_pass.set_pipeline(&self.pipeline); + render_pass.draw(0..3, 0..1); + } - render_pass.set_pipeline(&self.pipeline); - render_pass.draw(0..3, 0..1); + self.queue.submit(std::iter::once(encoder.finish())); + output.present(); } fn on_event( - &mut self, window: &mut baseview::Window, event: baseview::Event, + &mut self, _window: &mut baseview::Window, _event: baseview::Event, ) -> baseview::EventStatus { baseview::EventStatus::Captured } @@ -140,6 +143,7 @@ fn main() { title: "wgpu on baseview".into(), size: Size::new(512.0, 512.0), scale: baseview::WindowScalePolicy::SystemScaleFactor, + gl_config: None, }; Window::open_blocking(window_open_options, |window| { From 3a7facdfe3e4f4801f1cdf2f158ed461312f0c84 Mon Sep 17 00:00:00 2001 From: Andrew Thomas Date: Sun, 12 May 2024 12:58:40 -0700 Subject: [PATCH 4/9] we got a rainbow triangle --- examples/render_wgpu/Cargo.toml | 1 + examples/render_wgpu/src/main.rs | 48 +++++++++++++++++++++++++--- examples/render_wgpu/src/shader.wgsl | 16 ++++++---- 3 files changed, 54 insertions(+), 11 deletions(-) diff --git a/examples/render_wgpu/Cargo.toml b/examples/render_wgpu/Cargo.toml index 08e3c5d..a3ef800 100644 --- a/examples/render_wgpu/Cargo.toml +++ b/examples/render_wgpu/Cargo.toml @@ -9,3 +9,4 @@ edition = "2021" wgpu = "0.18" baseview = {path = "../..", features = ["opengl"]} pollster = "0.3.0" +bytemuck = {version = "1.15.0", features = ["derive"]} diff --git a/examples/render_wgpu/src/main.rs b/examples/render_wgpu/src/main.rs index 2a45696..86d6234 100644 --- a/examples/render_wgpu/src/main.rs +++ b/examples/render_wgpu/src/main.rs @@ -1,13 +1,12 @@ use baseview::{Size, Window, WindowHandler, WindowOpenOptions}; -use wgpu::{Device, Instance, Queue, RenderPipeline, Surface, SurfaceConfiguration}; +use wgpu::{util::DeviceExt, Buffer, Device, Queue, RenderPipeline, Surface}; struct WgpuExample { pipeline: RenderPipeline, device: Device, - config: SurfaceConfiguration, - instance: Instance, surface: Surface, queue: Queue, + vertex_buffer: Buffer, } impl<'a> WgpuExample { @@ -34,6 +33,12 @@ impl<'a> WgpuExample { .await .unwrap(); + let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("Vertex Buffer"), + contents: bytemuck::cast_slice(VERTICES), + usage: wgpu::BufferUsages::VERTEX, + }); + let surface_caps = surface.get_capabilities(&adapter); let surface_format = surface_caps .formats @@ -65,7 +70,11 @@ impl<'a> WgpuExample { let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { label: Some("Render Pipeline"), layout: Some(&render_pipeline_layout), - vertex: wgpu::VertexState { module: &shader, entry_point: "vs_main", buffers: &[] }, + vertex: wgpu::VertexState { + module: &shader, + entry_point: "vs_main", + buffers: &[Vertex::desc()], + }, fragment: Some(wgpu::FragmentState { module: &shader, entry_point: "fs_main", @@ -95,7 +104,7 @@ impl<'a> WgpuExample { surface.configure(&device, &config); - Self { pipeline, device, config, instance, surface, queue } + Self { pipeline, device, surface, queue, vertex_buffer } } } @@ -125,6 +134,7 @@ impl WindowHandler for WgpuExample { }); render_pass.set_pipeline(&self.pipeline); + render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..)); render_pass.draw(0..3, 0..1); } @@ -138,6 +148,34 @@ impl WindowHandler for WgpuExample { } } +#[repr(C)] +#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)] +struct Vertex { + position: [f32; 3], + color: [f32; 3], +} + +const VERTICES: &[Vertex] = &[ + Vertex { position: [0.0, 0.5, 0.0], color: [1.0, 0.0, 0.0] }, + Vertex { position: [-0.5, -0.5, 0.0], color: [0.0, 1.0, 0.0] }, + Vertex { position: [0.5, -0.5, 0.0], color: [0.0, 0.0, 1.0] }, +]; + +impl Vertex { + const ATTRIBS: [wgpu::VertexAttribute; 2] = + wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3]; + + fn desc() -> wgpu::VertexBufferLayout<'static> { + use std::mem; + + wgpu::VertexBufferLayout { + array_stride: mem::size_of::() as wgpu::BufferAddress, + step_mode: wgpu::VertexStepMode::Vertex, + attributes: &Self::ATTRIBS, + } + } +} + fn main() { let window_open_options = WindowOpenOptions { title: "wgpu on baseview".into(), diff --git a/examples/render_wgpu/src/shader.wgsl b/examples/render_wgpu/src/shader.wgsl index 7f0bb3a..cc394ed 100644 --- a/examples/render_wgpu/src/shader.wgsl +++ b/examples/render_wgpu/src/shader.wgsl @@ -1,17 +1,22 @@ // Vertex shader +struct VertexInput { + @location(0) position: vec3, + @location(1) color: vec3, +}; + struct VertexOutput { @builtin(position) clip_position: vec4, + @location(0) color: vec3, }; @vertex fn vs_main( - @builtin(vertex_index) in_vertex_index: u32, + model: VertexInput, ) -> VertexOutput { var out: VertexOutput; - let x = f32(1 - i32(in_vertex_index)) * 0.5; - let y = f32(i32(in_vertex_index & 1u) * 2 - 1) * 0.5; - out.clip_position = vec4(x, y, 0.0, 1.0); + out.color = model.color; + out.clip_position = vec4(model.position, 1.0); return out; } @@ -19,6 +24,5 @@ fn vs_main( @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4 { - return vec4(0.3, 0.2, 0.1, 1.0); + return vec4(in.color, 1.0); } - From e469af4fcf9ca89e3dff811ef1b66dc793df1c5b Mon Sep 17 00:00:00 2001 From: Andrew Thomas Date: Sun, 12 May 2024 13:31:01 -0700 Subject: [PATCH 5/9] ok cool i think we're there --- examples/render_wgpu/src/main.rs | 40 ++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/examples/render_wgpu/src/main.rs b/examples/render_wgpu/src/main.rs index 86d6234..d58aaf7 100644 --- a/examples/render_wgpu/src/main.rs +++ b/examples/render_wgpu/src/main.rs @@ -1,4 +1,4 @@ -use baseview::{Size, Window, WindowHandler, WindowOpenOptions}; +use baseview::{MouseEvent, Size, Window, WindowHandler, WindowInfo, WindowOpenOptions}; use wgpu::{util::DeviceExt, Buffer, Device, Queue, RenderPipeline, Surface}; struct WgpuExample { @@ -35,7 +35,7 @@ impl<'a> WgpuExample { let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { label: Some("Vertex Buffer"), - contents: bytemuck::cast_slice(VERTICES), + contents: bytemuck::cast_slice(VERTICES_START), usage: wgpu::BufferUsages::VERTEX, }); @@ -142,8 +142,34 @@ impl WindowHandler for WgpuExample { output.present(); } fn on_event( - &mut self, _window: &mut baseview::Window, _event: baseview::Event, + &mut self, _window: &mut baseview::Window, event: baseview::Event, ) -> baseview::EventStatus { + match event { + baseview::Event::Mouse(MouseEvent::CursorMoved { position, modifiers: _ }) => { + let center_x: f32 = (position.x as f32 - 256.0) / 256.0; + let center_y: f32 = (256.0 - position.y as f32) / 256.0; + let vertices = &[ + Vertex { position: [center_x, center_y + 0.25, 0.0], color: [1.0, 0.0, 0.0] }, + Vertex { + position: [center_x - 0.25, center_y - 0.25, 0.0], + color: [0.0, 1.0, 0.0], + }, + Vertex { + position: [center_x + 0.25, center_y - 0.25, 0.0], + color: [0.0, 0.0, 1.0], + }, + ]; + let vertex_buffer = + self.device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("Vertex Buffer"), + contents: bytemuck::cast_slice(vertices), + usage: wgpu::BufferUsages::VERTEX, + }); + + self.vertex_buffer = vertex_buffer; + } + _ => {} + } baseview::EventStatus::Captured } } @@ -155,10 +181,10 @@ struct Vertex { color: [f32; 3], } -const VERTICES: &[Vertex] = &[ - Vertex { position: [0.0, 0.5, 0.0], color: [1.0, 0.0, 0.0] }, - Vertex { position: [-0.5, -0.5, 0.0], color: [0.0, 1.0, 0.0] }, - Vertex { position: [0.5, -0.5, 0.0], color: [0.0, 0.0, 1.0] }, +const VERTICES_START: &[Vertex] = &[ + Vertex { position: [0.0, 0.25, 0.0], color: [1.0, 0.0, 0.0] }, + Vertex { position: [-0.25, -0.25, 0.0], color: [0.0, 1.0, 0.0] }, + Vertex { position: [0.25, -0.25, 0.0], color: [0.0, 0.0, 1.0] }, ]; impl Vertex { From 29e9aec327f0ee48f9544aeaf840f0e67d8c0a6c Mon Sep 17 00:00:00 2001 From: Andrew Thomas Date: Sun, 12 May 2024 13:43:45 -0700 Subject: [PATCH 6/9] fixed unused import error --- examples/render_wgpu/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/render_wgpu/src/main.rs b/examples/render_wgpu/src/main.rs index d58aaf7..657ff1c 100644 --- a/examples/render_wgpu/src/main.rs +++ b/examples/render_wgpu/src/main.rs @@ -1,4 +1,4 @@ -use baseview::{MouseEvent, Size, Window, WindowHandler, WindowInfo, WindowOpenOptions}; +use baseview::{MouseEvent, Size, Window, WindowHandler, WindowOpenOptions}; use wgpu::{util::DeviceExt, Buffer, Device, Queue, RenderPipeline, Surface}; struct WgpuExample { From 03b60d5fd0bba278a67e9a2d5efce02c71699bee Mon Sep 17 00:00:00 2001 From: Andrew Thomas Date: Mon, 13 May 2024 07:02:13 -0700 Subject: [PATCH 7/9] fixing clippy errors --- examples/render_wgpu/src/main.rs | 49 ++++++++++++++------------------ 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/examples/render_wgpu/src/main.rs b/examples/render_wgpu/src/main.rs index 657ff1c..0ef2628 100644 --- a/examples/render_wgpu/src/main.rs +++ b/examples/render_wgpu/src/main.rs @@ -44,8 +44,7 @@ impl<'a> WgpuExample { .formats .iter() .copied() - .filter(|f| f.is_srgb()) - .next() + .find(|f| f.is_srgb()) .unwrap_or(surface_caps.formats[0]); let config = wgpu::SurfaceConfiguration { usage: wgpu::TextureUsages::RENDER_ATTACHMENT, @@ -144,31 +143,27 @@ impl WindowHandler for WgpuExample { fn on_event( &mut self, _window: &mut baseview::Window, event: baseview::Event, ) -> baseview::EventStatus { - match event { - baseview::Event::Mouse(MouseEvent::CursorMoved { position, modifiers: _ }) => { - let center_x: f32 = (position.x as f32 - 256.0) / 256.0; - let center_y: f32 = (256.0 - position.y as f32) / 256.0; - let vertices = &[ - Vertex { position: [center_x, center_y + 0.25, 0.0], color: [1.0, 0.0, 0.0] }, - Vertex { - position: [center_x - 0.25, center_y - 0.25, 0.0], - color: [0.0, 1.0, 0.0], - }, - Vertex { - position: [center_x + 0.25, center_y - 0.25, 0.0], - color: [0.0, 0.0, 1.0], - }, - ]; - let vertex_buffer = - self.device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some("Vertex Buffer"), - contents: bytemuck::cast_slice(vertices), - usage: wgpu::BufferUsages::VERTEX, - }); - - self.vertex_buffer = vertex_buffer; - } - _ => {} + if let baseview::Event::Mouse(MouseEvent::CursorMoved { position, modifiers: _ }) = event { + let center_x: f32 = (position.x as f32 - 256.0) / 256.0; + let center_y: f32 = (256.0 - position.y as f32) / 256.0; + let vertices = &[ + Vertex { position: [center_x, center_y + 0.25, 0.0], color: [1.0, 0.0, 0.0] }, + Vertex { + position: [center_x - 0.25, center_y - 0.25, 0.0], + color: [0.0, 1.0, 0.0], + }, + Vertex { + position: [center_x + 0.25, center_y - 0.25, 0.0], + color: [0.0, 0.0, 1.0], + }, + ]; + let vertex_buffer = self.device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("Vertex Buffer"), + contents: bytemuck::cast_slice(vertices), + usage: wgpu::BufferUsages::VERTEX, + }); + + self.vertex_buffer = vertex_buffer; } baseview::EventStatus::Captured } From 2174d2330b20665cb1f1df97d2611f299b3ea881 Mon Sep 17 00:00:00 2001 From: Andrew Thomas Date: Mon, 13 May 2024 11:59:18 -0700 Subject: [PATCH 8/9] fixed window size issue --- examples/render_wgpu/src/main.rs | 78 ++++++++++++++++++---------- examples/render_wgpu/src/shader.wgsl | 4 -- 2 files changed, 52 insertions(+), 30 deletions(-) diff --git a/examples/render_wgpu/src/main.rs b/examples/render_wgpu/src/main.rs index 0ef2628..638bf00 100644 --- a/examples/render_wgpu/src/main.rs +++ b/examples/render_wgpu/src/main.rs @@ -1,5 +1,5 @@ use baseview::{MouseEvent, Size, Window, WindowHandler, WindowOpenOptions}; -use wgpu::{util::DeviceExt, Buffer, Device, Queue, RenderPipeline, Surface}; +use wgpu::{util::DeviceExt, Buffer, Device, Queue, RenderPipeline, Surface, SurfaceCapabilities}; struct WgpuExample { pipeline: RenderPipeline, @@ -7,6 +7,7 @@ struct WgpuExample { surface: Surface, queue: Queue, vertex_buffer: Buffer, + surface_caps: SurfaceCapabilities, } impl<'a> WgpuExample { @@ -49,9 +50,8 @@ impl<'a> WgpuExample { let config = wgpu::SurfaceConfiguration { usage: wgpu::TextureUsages::RENDER_ATTACHMENT, format: surface_format, - // TODO this needs to be twice the window size for some reason - width: 1024, - height: 1024, + width: 512, + height: 512, present_mode: surface_caps.present_modes[0], alpha_mode: surface_caps.alpha_modes[0], view_formats: vec![], @@ -103,7 +103,7 @@ impl<'a> WgpuExample { surface.configure(&device, &config); - Self { pipeline, device, surface, queue, vertex_buffer } + Self { pipeline, device, surface, queue, vertex_buffer, surface_caps } } } @@ -143,27 +143,53 @@ impl WindowHandler for WgpuExample { fn on_event( &mut self, _window: &mut baseview::Window, event: baseview::Event, ) -> baseview::EventStatus { - if let baseview::Event::Mouse(MouseEvent::CursorMoved { position, modifiers: _ }) = event { - let center_x: f32 = (position.x as f32 - 256.0) / 256.0; - let center_y: f32 = (256.0 - position.y as f32) / 256.0; - let vertices = &[ - Vertex { position: [center_x, center_y + 0.25, 0.0], color: [1.0, 0.0, 0.0] }, - Vertex { - position: [center_x - 0.25, center_y - 0.25, 0.0], - color: [0.0, 1.0, 0.0], - }, - Vertex { - position: [center_x + 0.25, center_y - 0.25, 0.0], - color: [0.0, 0.0, 1.0], - }, - ]; - let vertex_buffer = self.device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some("Vertex Buffer"), - contents: bytemuck::cast_slice(vertices), - usage: wgpu::BufferUsages::VERTEX, - }); - - self.vertex_buffer = vertex_buffer; + match event { + baseview::Event::Mouse(MouseEvent::CursorMoved { position, modifiers: _ }) => { + let center_x: f32 = (position.x as f32 - 256.0) / 256.0; + let center_y: f32 = (256.0 - position.y as f32) / 256.0; + let vertices = &[ + Vertex { position: [center_x, center_y + 0.25, 0.0], color: [1.0, 0.0, 0.0] }, + Vertex { + position: [center_x - 0.25, center_y - 0.25, 0.0], + color: [0.0, 1.0, 0.0], + }, + Vertex { + position: [center_x + 0.25, center_y - 0.25, 0.0], + color: [0.0, 0.0, 1.0], + }, + ]; + let vertex_buffer = + self.device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("Vertex Buffer"), + contents: bytemuck::cast_slice(vertices), + usage: wgpu::BufferUsages::VERTEX, + }); + + self.vertex_buffer = vertex_buffer; + } + baseview::Event::Window(baseview::WindowEvent::Resized(size)) => { + let surface_format = self + .surface_caps + .formats + .iter() + .copied() + .find(|f| f.is_srgb()) + .unwrap_or(self.surface_caps.formats[0]); + + self.surface.configure( + &self.device, + &wgpu::SurfaceConfiguration { + usage: wgpu::TextureUsages::RENDER_ATTACHMENT, + format: surface_format, + width: size.physical_size().width, + height: size.physical_size().height, + present_mode: self.surface_caps.present_modes[0], + alpha_mode: self.surface_caps.alpha_modes[0], + view_formats: vec![], + }, + ) + } + _ => {} } baseview::EventStatus::Captured } diff --git a/examples/render_wgpu/src/shader.wgsl b/examples/render_wgpu/src/shader.wgsl index cc394ed..68f015a 100644 --- a/examples/render_wgpu/src/shader.wgsl +++ b/examples/render_wgpu/src/shader.wgsl @@ -1,5 +1,3 @@ -// Vertex shader - struct VertexInput { @location(0) position: vec3, @location(1) color: vec3, @@ -20,8 +18,6 @@ fn vs_main( return out; } -// Fragment shader - @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4 { return vec4(in.color, 1.0); From 7dfbe082ce9fee23fa539019c7634dce591ab9ff Mon Sep 17 00:00:00 2001 From: Andrew Thomas Date: Mon, 13 May 2024 12:28:44 -0700 Subject: [PATCH 9/9] used uniform buffer instead of making new vertex buffer every time --- examples/render_wgpu/src/main.rs | 97 +++++++++++++++++++--------- examples/render_wgpu/src/shader.wgsl | 4 +- 2 files changed, 70 insertions(+), 31 deletions(-) diff --git a/examples/render_wgpu/src/main.rs b/examples/render_wgpu/src/main.rs index 638bf00..3621124 100644 --- a/examples/render_wgpu/src/main.rs +++ b/examples/render_wgpu/src/main.rs @@ -1,5 +1,9 @@ use baseview::{MouseEvent, Size, Window, WindowHandler, WindowOpenOptions}; -use wgpu::{util::DeviceExt, Buffer, Device, Queue, RenderPipeline, Surface, SurfaceCapabilities}; +use wgpu::{ + util::DeviceExt, BindGroup, Buffer, Device, Queue, RenderPipeline, Surface, SurfaceCapabilities, +}; + +const WINDOW_SIZE: u32 = 512; struct WgpuExample { pipeline: RenderPipeline, @@ -7,7 +11,10 @@ struct WgpuExample { surface: Surface, queue: Queue, vertex_buffer: Buffer, + mouse_pos_buffer: Buffer, surface_caps: SurfaceCapabilities, + bind_group: BindGroup, + size: (u32, u32), } impl<'a> WgpuExample { @@ -40,6 +47,33 @@ impl<'a> WgpuExample { usage: wgpu::BufferUsages::VERTEX, }); + let mouse_pos_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("mouse position buffer"), + contents: bytemuck::cast_slice(&[0.0, 0.0]), + usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, + }); + let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::VERTEX, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }], + }); + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: None, + layout: &bind_group_layout, + entries: &[wgpu::BindGroupEntry { + binding: 0, + resource: mouse_pos_buffer.as_entire_binding(), + }], + }); + let surface_caps = surface.get_capabilities(&adapter); let surface_format = surface_caps .formats @@ -50,8 +84,8 @@ impl<'a> WgpuExample { let config = wgpu::SurfaceConfiguration { usage: wgpu::TextureUsages::RENDER_ATTACHMENT, format: surface_format, - width: 512, - height: 512, + width: WINDOW_SIZE, + height: WINDOW_SIZE, present_mode: surface_caps.present_modes[0], alpha_mode: surface_caps.alpha_modes[0], view_formats: vec![], @@ -62,7 +96,7 @@ impl<'a> WgpuExample { let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Render Pipeline Layout"), - bind_group_layouts: &[], + bind_group_layouts: &[&bind_group_layout], push_constant_ranges: &[], }); @@ -103,7 +137,17 @@ impl<'a> WgpuExample { surface.configure(&device, &config); - Self { pipeline, device, surface, queue, vertex_buffer, surface_caps } + Self { + pipeline, + device, + surface, + queue, + vertex_buffer, + surface_caps, + bind_group, + mouse_pos_buffer, + size: (WINDOW_SIZE, WINDOW_SIZE), + } } } @@ -133,6 +177,7 @@ impl WindowHandler for WgpuExample { }); render_pass.set_pipeline(&self.pipeline); + render_pass.set_bind_group(0, &self.bind_group, &[]); render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..)); render_pass.draw(0..3, 0..1); } @@ -145,29 +190,21 @@ impl WindowHandler for WgpuExample { ) -> baseview::EventStatus { match event { baseview::Event::Mouse(MouseEvent::CursorMoved { position, modifiers: _ }) => { - let center_x: f32 = (position.x as f32 - 256.0) / 256.0; - let center_y: f32 = (256.0 - position.y as f32) / 256.0; - let vertices = &[ - Vertex { position: [center_x, center_y + 0.25, 0.0], color: [1.0, 0.0, 0.0] }, - Vertex { - position: [center_x - 0.25, center_y - 0.25, 0.0], - color: [0.0, 1.0, 0.0], - }, - Vertex { - position: [center_x + 0.25, center_y - 0.25, 0.0], - color: [0.0, 0.0, 1.0], - }, - ]; - let vertex_buffer = - self.device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some("Vertex Buffer"), - contents: bytemuck::cast_slice(vertices), - usage: wgpu::BufferUsages::VERTEX, - }); - - self.vertex_buffer = vertex_buffer; + let center_x: f32 = + (position.x as f32 - (self.size.0 as f32 / 2.0)) / (self.size.0 as f32 / 2.0); + let center_y: f32 = + ((self.size.1 as f32 / 2.0) - position.y as f32) / (self.size.1 as f32 / 2.0); + + self.queue.write_buffer( + &self.mouse_pos_buffer, + 0, + bytemuck::cast_slice(&[center_x, center_y]), + ) } baseview::Event::Window(baseview::WindowEvent::Resized(size)) => { + let width = size.physical_size().width; + let height = size.physical_size().height; + let surface_format = self .surface_caps .formats @@ -181,13 +218,13 @@ impl WindowHandler for WgpuExample { &wgpu::SurfaceConfiguration { usage: wgpu::TextureUsages::RENDER_ATTACHMENT, format: surface_format, - width: size.physical_size().width, - height: size.physical_size().height, + width, + height, present_mode: self.surface_caps.present_modes[0], alpha_mode: self.surface_caps.alpha_modes[0], view_formats: vec![], }, - ) + ); } _ => {} } @@ -226,7 +263,7 @@ impl Vertex { fn main() { let window_open_options = WindowOpenOptions { title: "wgpu on baseview".into(), - size: Size::new(512.0, 512.0), + size: Size::new(WINDOW_SIZE as f64, WINDOW_SIZE as f64), scale: baseview::WindowScalePolicy::SystemScaleFactor, gl_config: None, }; diff --git a/examples/render_wgpu/src/shader.wgsl b/examples/render_wgpu/src/shader.wgsl index 68f015a..4501ecd 100644 --- a/examples/render_wgpu/src/shader.wgsl +++ b/examples/render_wgpu/src/shader.wgsl @@ -1,3 +1,5 @@ +@group(0) @binding(0) var mouse_pos: vec2; + struct VertexInput { @location(0) position: vec3, @location(1) color: vec3, @@ -14,7 +16,7 @@ fn vs_main( ) -> VertexOutput { var out: VertexOutput; out.color = model.color; - out.clip_position = vec4(model.position, 1.0); + out.clip_position = vec4(model.position.x + mouse_pos.x, model.position.y + mouse_pos.y, model.position.z, 1.0); return out; }