diff --git a/.gitignore b/.gitignore index 995d5e195..c035154ac 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ target/ **/*.rs.bk Cargo.lock .DS_Store +.idea/ diff --git a/examples/Cargo.toml b/examples/Cargo.toml index f1f8b4c6d..943933f9e 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -14,7 +14,6 @@ homepage = "https://github.com/nannou-org/nannou" edition = "2018" [dev-dependencies] -async-std = "1.10.0" audrey = "0.3" hotglsl = { git = "https://github.com/nannou-org/hotglsl", branch = "master" } hrtf = "0.2" @@ -29,6 +28,12 @@ time_calc = { version= "0.13", features = ["serde"] } walkdir = "2" hound = "3.4.0" ringbuf = "0.2.2" +futures = "0.3" + +[target.'cfg(not(target_arch = "wasm32"))'.dependencies] +tokio = { version = "1", features = ["full"]} +[target.'cfg(target_arch = "wasm32")'.dependencies] +tokio = { version = "1", features = ["rt"]} # Audio [[example]] diff --git a/examples/laser/laser_frame_stream_gui.rs b/examples/laser/laser_frame_stream_gui.rs index f8e11f043..e69d8b9b1 100644 --- a/examples/laser/laser_frame_stream_gui.rs +++ b/examples/laser/laser_frame_stream_gui.rs @@ -3,6 +3,7 @@ use nannou::geom::Rect; use nannou::prelude::*; +use nannou_egui::egui::FontId; use nannou_egui::{self, egui, Egui}; use nannou_laser as laser; use std::sync::{mpsc, Arc}; @@ -155,7 +156,6 @@ fn model(app: &App) -> Model { // A user-interface to tweak the settings. let window = app.window(w_id).unwrap(); let egui = Egui::from_window(&window); - egui.ctx().set_fonts(fonts()); egui.ctx().set_style(style()); Model { @@ -278,7 +278,7 @@ fn raw_window_event(_app: &App, model: &mut Model, event: &nannou::winit::event: fn update(_app: &App, model: &mut Model, update: Update) { // First, check for new laser DACs. - for dac in model.dac_rx.try_recv() { + for dac in model.dac_rx.try_iter() { println!("Detected DAC {:?}!", dac.id()); let stream = model .laser_api @@ -510,39 +510,16 @@ fn view(_app: &App, model: &Model, frame: Frame) { // The following functions are some custom styling preferences in an attempt to improve on the // default egui theming. -fn fonts() -> egui::FontDefinitions { - let mut fonts = egui::FontDefinitions::default(); - let entries = [ - ( - egui::TextStyle::Small, - (egui::FontFamily::Proportional, 13.0), - ), - ( - egui::TextStyle::Body, - (egui::FontFamily::Proportional, 16.0), - ), - ( - egui::TextStyle::Button, - (egui::FontFamily::Proportional, 16.0), - ), - ( - egui::TextStyle::Heading, - (egui::FontFamily::Proportional, 20.0), - ), - ( - egui::TextStyle::Monospace, - (egui::FontFamily::Monospace, 14.0), - ), - ]; - fonts.family_and_size.extend(entries.iter().cloned()); - fonts -} - fn style() -> egui::Style { let mut style = egui::Style::default(); style.spacing = egui::style::Spacing { item_spacing: egui::Vec2::splat(8.0), - window_padding: egui::Vec2::new(6.0, 6.0), + window_margin: egui::Margin { + left: 6.0, + right: 6.0, + top: 6.0, + bottom: 6.0, + }, button_padding: egui::Vec2::new(4.0, 2.0), interact_size: egui::Vec2::new(56.0, 24.0), indent: 10.0, @@ -556,5 +533,28 @@ fn style() -> egui::Style { style.visuals.widgets.noninteractive.bg_fill = egui::Color32::from_gray(36); style.visuals.widgets.noninteractive.bg_stroke.color = egui::Color32::BLACK; style.visuals.widgets.noninteractive.fg_stroke.color = egui::Color32::WHITE; + style.text_styles = [ + ( + egui::TextStyle::Small, + FontId::new(13.0, egui::FontFamily::Proportional), + ), + ( + egui::TextStyle::Body, + FontId::new(16.0, egui::FontFamily::Proportional), + ), + ( + egui::TextStyle::Button, + FontId::new(16.0, egui::FontFamily::Proportional), + ), + ( + egui::TextStyle::Heading, + FontId::new(20.0, egui::FontFamily::Proportional), + ), + ( + egui::TextStyle::Monospace, + FontId::new(14.0, egui::FontFamily::Monospace), + ), + ] + .into(); style } diff --git a/examples/ui/egui/tune_color.rs b/examples/ui/egui/tune_color.rs index 6e7b9e4b0..dc0ceae59 100644 --- a/examples/ui/egui/tune_color.rs +++ b/examples/ui/egui/tune_color.rs @@ -75,7 +75,7 @@ fn view(app: &App, model: &Model, frame: Frame) { } fn edit_hsv(ui: &mut egui::Ui, color: &mut Hsv) { - let mut egui_hsv = egui::color::Hsva::new( + let mut egui_hsv = egui::ecolor::Hsva::new( color.hue.to_positive_radians() as f32 / (std::f32::consts::PI * 2.0), color.saturation, color.value, diff --git a/examples/wgpu/wgpu_compute_shader/shaders/cs.wgsl b/examples/wgpu/wgpu_compute_shader/shaders/cs.wgsl index e10148821..9daac0bfc 100644 --- a/examples/wgpu/wgpu_compute_shader/shaders/cs.wgsl +++ b/examples/wgpu/wgpu_compute_shader/shaders/cs.wgsl @@ -1,22 +1,20 @@ -[[block]] struct Buffer { - data: [[stride(4)]] array; + data: array, }; -[[block]] struct Uniforms { - time: f32; - freq: f32; - oscillator_count: u32; + time: f32, + freq: f32, + oscillator_count: u32, }; -[[group(0), binding(0)]] +@group(0) @binding(0) var output: Buffer; -[[group(0), binding(1)]] +@group(0) @binding(1) var uniforms: Uniforms; -[[stage(compute), workgroup_size(1, 1, 1)]] -fn main([[builtin(global_invocation_id)]] id: vec3) { +@compute @workgroup_size(1, 1, 1) +fn main(@builtin(global_invocation_id) id: vec3) { let index: u32 = id.x; let phase: f32 = uniforms.time + f32(index) * uniforms.freq / f32(uniforms.oscillator_count); output.data[index] = sin(phase) * 0.5 + 0.5; diff --git a/examples/wgpu/wgpu_compute_shader/wgpu_compute_shader.rs b/examples/wgpu/wgpu_compute_shader/wgpu_compute_shader.rs index 6e7eaaae7..518b00200 100644 --- a/examples/wgpu/wgpu_compute_shader/wgpu_compute_shader.rs +++ b/examples/wgpu/wgpu_compute_shader/wgpu_compute_shader.rs @@ -43,7 +43,7 @@ fn model(app: &App) -> Model { // Create the compute shader module. let cs_desc = wgpu::include_wgsl!("shaders/cs.wgsl"); - let cs_mod = device.create_shader_module(&cs_desc); + let cs_mod = device.create_shader_module(cs_desc); // Create the buffer that will store the result of our compute operation. let oscillator_buffer_size = @@ -140,7 +140,7 @@ fn update(app: &App, model: &mut Model, _update: Update) { let mut cpass = encoder.begin_compute_pass(&pass_desc); cpass.set_pipeline(&compute.pipeline); cpass.set_bind_group(0, &compute.bind_group, &[]); - cpass.dispatch(OSCILLATOR_COUNT as u32, 1, 1); + cpass.dispatch_workgroups(OSCILLATOR_COUNT as u32, 1, 1); } encoder.copy_buffer_to_buffer( &compute.oscillator_buffer, @@ -157,7 +157,11 @@ fn update(app: &App, model: &mut Model, _update: Update) { let oscillators = model.oscillators.clone(); let future = async move { let slice = read_buffer.slice(..); - if let Ok(_) = slice.map_async(wgpu::MapMode::Read).await { + let (tx, rx) = futures::channel::oneshot::channel(); + slice.map_async(wgpu::MapMode::Read, |res| { + tx.send(res).expect("The channel was closed"); + }); + if let Ok(_) = rx.await { if let Ok(mut oscillators) = oscillators.lock() { let bytes = &slice.get_mapped_range()[..]; // "Cast" the slice of bytes to a slice of floats as required. @@ -170,7 +174,7 @@ fn update(app: &App, model: &mut Model, _update: Update) { } } }; - async_std::task::spawn(future); + tokio::spawn(future); // Check for resource cleanups and mapping callbacks. // diff --git a/examples/wgpu/wgpu_image/shaders/fs.wgsl b/examples/wgpu/wgpu_image/shaders/fs.wgsl index 597ac5f0f..5fd305572 100644 --- a/examples/wgpu/wgpu_image/shaders/fs.wgsl +++ b/examples/wgpu/wgpu_image/shaders/fs.wgsl @@ -1,14 +1,14 @@ struct FragmentOutput { - [[location(0)]] f_color: vec4; + @location(0) f_color: vec4, }; -[[group(0), binding(0)]] +@group(0) @binding(0) var tex: texture_2d; -[[group(0), binding(1)]] +@group(0) @binding(1) var tex_sampler: sampler; -[[stage(fragment)]] -fn main([[location(0)]] tex_coords: vec2) -> FragmentOutput { +@fragment +fn main(@location(0) tex_coords: vec2) -> FragmentOutput { let out_color: vec4 = textureSample(tex, tex_sampler, tex_coords); return FragmentOutput(out_color); } diff --git a/examples/wgpu/wgpu_image/shaders/vs.wgsl b/examples/wgpu/wgpu_image/shaders/vs.wgsl index a83a0da30..e9925b28b 100644 --- a/examples/wgpu/wgpu_image/shaders/vs.wgsl +++ b/examples/wgpu/wgpu_image/shaders/vs.wgsl @@ -1,10 +1,10 @@ struct VertexOutput { - [[location(0)]] tex_coords: vec2; - [[builtin(position)]] out_pos: vec4; + @location(0) tex_coords: vec2, + @builtin(position) out_pos: vec4, }; -[[stage(vertex)]] -fn main([[location(0)]] pos: vec2) -> VertexOutput { +@vertex +fn main(@location(0) pos: vec2) -> VertexOutput { let tex_coords: vec2 = vec2(pos.x * 0.5 + 0.5, 1.0 - (pos.y * 0.5 + 0.5)); let out_pos: vec4 = vec4(pos, 0.0, 1.0); return VertexOutput(tex_coords, out_pos); diff --git a/examples/wgpu/wgpu_image/wgpu_image.rs b/examples/wgpu/wgpu_image/wgpu_image.rs index 84f6a5d4a..156c4390c 100644 --- a/examples/wgpu/wgpu_image/wgpu_image.rs +++ b/examples/wgpu/wgpu_image/wgpu_image.rs @@ -54,8 +54,8 @@ fn model(app: &App) -> Model { let vs_desc = wgpu::include_wgsl!("shaders/vs.wgsl"); let fs_desc = wgpu::include_wgsl!("shaders/fs.wgsl"); - let vs_mod = device.create_shader_module(&vs_desc); - let fs_mod = device.create_shader_module(&fs_desc); + let vs_mod = device.create_shader_module(vs_desc); + let fs_mod = device.create_shader_module(fs_desc); // Load the image as a texture. let texture = wgpu::Texture::from_image(&window, &image); diff --git a/examples/wgpu/wgpu_image_sequence/shaders/fs.wgsl b/examples/wgpu/wgpu_image_sequence/shaders/fs.wgsl index 597ac5f0f..5fd305572 100644 --- a/examples/wgpu/wgpu_image_sequence/shaders/fs.wgsl +++ b/examples/wgpu/wgpu_image_sequence/shaders/fs.wgsl @@ -1,14 +1,14 @@ struct FragmentOutput { - [[location(0)]] f_color: vec4; + @location(0) f_color: vec4, }; -[[group(0), binding(0)]] +@group(0) @binding(0) var tex: texture_2d; -[[group(0), binding(1)]] +@group(0) @binding(1) var tex_sampler: sampler; -[[stage(fragment)]] -fn main([[location(0)]] tex_coords: vec2) -> FragmentOutput { +@fragment +fn main(@location(0) tex_coords: vec2) -> FragmentOutput { let out_color: vec4 = textureSample(tex, tex_sampler, tex_coords); return FragmentOutput(out_color); } diff --git a/examples/wgpu/wgpu_image_sequence/shaders/vs.wgsl b/examples/wgpu/wgpu_image_sequence/shaders/vs.wgsl index a83a0da30..e9925b28b 100644 --- a/examples/wgpu/wgpu_image_sequence/shaders/vs.wgsl +++ b/examples/wgpu/wgpu_image_sequence/shaders/vs.wgsl @@ -1,10 +1,10 @@ struct VertexOutput { - [[location(0)]] tex_coords: vec2; - [[builtin(position)]] out_pos: vec4; + @location(0) tex_coords: vec2, + @builtin(position) out_pos: vec4, }; -[[stage(vertex)]] -fn main([[location(0)]] pos: vec2) -> VertexOutput { +@vertex +fn main(@location(0) pos: vec2) -> VertexOutput { let tex_coords: vec2 = vec2(pos.x * 0.5 + 0.5, 1.0 - (pos.y * 0.5 + 0.5)); let out_pos: vec4 = vec4(pos, 0.0, 1.0); return VertexOutput(tex_coords, out_pos); diff --git a/examples/wgpu/wgpu_image_sequence/wgpu_image_sequence.rs b/examples/wgpu/wgpu_image_sequence/wgpu_image_sequence.rs index 7bd98a74a..6291353a0 100644 --- a/examples/wgpu/wgpu_image_sequence/wgpu_image_sequence.rs +++ b/examples/wgpu/wgpu_image_sequence/wgpu_image_sequence.rs @@ -78,8 +78,8 @@ fn model(app: &App) -> Model { let vs_desc = wgpu::include_wgsl!("shaders/vs.wgsl"); let fs_desc = wgpu::include_wgsl!("shaders/fs.wgsl"); - let vs_mod = device.create_shader_module(&vs_desc); - let fs_mod = device.create_shader_module(&fs_desc); + let vs_mod = device.create_shader_module(vs_desc); + let fs_mod = device.create_shader_module(fs_desc); let texture_array = { // The wgpu device queue used to load the image data. diff --git a/examples/wgpu/wgpu_instancing/shaders/fs.wgsl b/examples/wgpu/wgpu_instancing/shaders/fs.wgsl index 9d0c0fa05..306d23040 100644 --- a/examples/wgpu/wgpu_instancing/shaders/fs.wgsl +++ b/examples/wgpu/wgpu_instancing/shaders/fs.wgsl @@ -1,11 +1,11 @@ struct FragmentOutput { - [[location(0)]] f_color: vec4; + @location(0) f_color: vec4, }; -[[stage(fragment)]] +@fragment fn main( - [[location(0)]] normal: vec3, - [[location(1)]] color: vec3, + @location(0) normal: vec3, + @location(1) color: vec3, ) -> FragmentOutput { let light: vec3 = vec3(0.0, 0.0, 1.0); let brightness: f32 = dot(normalize(normal), normalize(light)); diff --git a/examples/wgpu/wgpu_instancing/shaders/vs.wgsl b/examples/wgpu/wgpu_instancing/shaders/vs.wgsl index 0e8889f06..dbf944694 100644 --- a/examples/wgpu/wgpu_instancing/shaders/vs.wgsl +++ b/examples/wgpu/wgpu_instancing/shaders/vs.wgsl @@ -1,17 +1,16 @@ -[[block]] struct Data { - world: mat4x4; - view: mat4x4; - proj: mat4x4; + world: mat4x4, + view: mat4x4, + proj: mat4x4, }; struct VertexOutput { - [[location(0)]] out_normal: vec3; - [[location(1)]] out_color: vec3; - [[builtin(position)]] out_pos: vec4; + @location(0) out_normal: vec3, + @location(1) out_color: vec3, + @builtin(position) out_pos: vec4, }; -[[group(0), binding(0)]] +@group(0) @binding(0) var uniforms: Data; fn custom_inverse(m: mat3x3) -> mat3x3 { @@ -30,15 +29,15 @@ fn custom_inverse(m: mat3x3) -> mat3x3 { return minv; } -[[stage(vertex)]] +@vertex fn main( - [[location(0)]] pos: vec3, - [[location(1)]] normal: vec3, - [[location(2)]] mat0: vec4, - [[location(3)]] mat1: vec4, - [[location(4)]] mat2: vec4, - [[location(5)]] mat3: vec4, - [[location(6)]] color: vec3, + @location(0) pos: vec3, + @location(1) normal: vec3, + @location(2) mat0: vec4, + @location(3) mat1: vec4, + @location(4) mat2: vec4, + @location(5) mat3: vec4, + @location(6) color: vec3, ) -> VertexOutput { let instance_transform: mat4x4 = mat4x4(mat0, mat1, mat2, mat3); let worldview: mat4x4 = uniforms.view * uniforms.world * instance_transform; diff --git a/examples/wgpu/wgpu_instancing/wgpu_instancing.rs b/examples/wgpu/wgpu_instancing/wgpu_instancing.rs index 5379d7c12..1cd053031 100644 --- a/examples/wgpu/wgpu_instancing/wgpu_instancing.rs +++ b/examples/wgpu/wgpu_instancing/wgpu_instancing.rs @@ -163,8 +163,8 @@ fn model(app: &App) -> Model { // Load shader modules. let vs_desc = wgpu::include_wgsl!("shaders/vs.wgsl"); let fs_desc = wgpu::include_wgsl!("shaders/fs.wgsl"); - let vs_mod = device.create_shader_module(&vs_desc); - let fs_mod = device.create_shader_module(&fs_desc); + let vs_mod = device.create_shader_module(vs_desc); + let fs_mod = device.create_shader_module(fs_desc); // Create the vertex, normal and index buffers. let vertices_bytes = vertices_as_bytes(&data::VERTICES); diff --git a/examples/wgpu/wgpu_teapot/shaders/fs.wgsl b/examples/wgpu/wgpu_teapot/shaders/fs.wgsl index 33dc55837..6a5079bbc 100644 --- a/examples/wgpu/wgpu_teapot/shaders/fs.wgsl +++ b/examples/wgpu/wgpu_teapot/shaders/fs.wgsl @@ -1,5 +1,5 @@ -[[stage(fragment)]] -fn main([[location(0)]] normal: vec3) -> [[location(0)]] vec4 { +@fragment +fn main(@location(0) normal: vec3) -> @location(0) vec4 { let light: vec3 = vec3(0.0, 0.0, 1.0); let color: vec3 = vec3(1.0); let brightness: f32 = dot(normalize(normal), normalize(light)); diff --git a/examples/wgpu/wgpu_teapot/shaders/vs.wgsl b/examples/wgpu/wgpu_teapot/shaders/vs.wgsl index 2bcd6f542..856e1f018 100644 --- a/examples/wgpu/wgpu_teapot/shaders/vs.wgsl +++ b/examples/wgpu/wgpu_teapot/shaders/vs.wgsl @@ -1,16 +1,15 @@ -[[block]] struct Data { - world: mat4x4; - view: mat4x4; - proj: mat4x4; + world: mat4x4, + view: mat4x4, + proj: mat4x4, }; struct VertexOutput { - [[location(0)]] normal: vec3; - [[builtin(position)]] pos: vec4; + @location(0) normal: vec3, + @builtin(position) pos: vec4, }; -[[group(0), binding(0)]] +@group(0) @binding(0) var uniforms: Data; fn custom_inverse(m: mat3x3) -> mat3x3 { @@ -29,10 +28,10 @@ fn custom_inverse(m: mat3x3) -> mat3x3 { return minv; } -[[stage(vertex)]] +@vertex fn main( - [[location(0)]] pos: vec3, - [[location(1)]] normal: vec3, + @location(0) pos: vec3, + @location(1) normal: vec3, ) -> VertexOutput { let worldview: mat4x4 = uniforms.view * uniforms.world; let wv3: mat3x3 = mat3x3(worldview[0].xyz, worldview[1].xyz, worldview[2].xyz); diff --git a/examples/wgpu/wgpu_teapot/wgpu_teapot.rs b/examples/wgpu/wgpu_teapot/wgpu_teapot.rs index b1797cebe..65dedd173 100644 --- a/examples/wgpu/wgpu_teapot/wgpu_teapot.rs +++ b/examples/wgpu/wgpu_teapot/wgpu_teapot.rs @@ -58,8 +58,8 @@ fn model(app: &App) -> Model { // Load shader modules. let vs_desc = wgpu::include_wgsl!("shaders/vs.wgsl"); let fs_desc = wgpu::include_wgsl!("shaders/fs.wgsl"); - let vs_mod = device.create_shader_module(&vs_desc); - let fs_mod = device.create_shader_module(&fs_desc); + let vs_mod = device.create_shader_module(vs_desc); + let fs_mod = device.create_shader_module(fs_desc); // Create the vertex, normal and index buffers. let vertices_bytes = vertices_as_bytes(&data::VERTICES); diff --git a/examples/wgpu/wgpu_teapot_camera/shaders/fs.wgsl b/examples/wgpu/wgpu_teapot_camera/shaders/fs.wgsl index 33dc55837..6a5079bbc 100644 --- a/examples/wgpu/wgpu_teapot_camera/shaders/fs.wgsl +++ b/examples/wgpu/wgpu_teapot_camera/shaders/fs.wgsl @@ -1,5 +1,5 @@ -[[stage(fragment)]] -fn main([[location(0)]] normal: vec3) -> [[location(0)]] vec4 { +@fragment +fn main(@location(0) normal: vec3) -> @location(0) vec4 { let light: vec3 = vec3(0.0, 0.0, 1.0); let color: vec3 = vec3(1.0); let brightness: f32 = dot(normalize(normal), normalize(light)); diff --git a/examples/wgpu/wgpu_teapot_camera/shaders/vs.wgsl b/examples/wgpu/wgpu_teapot_camera/shaders/vs.wgsl index 2bcd6f542..856e1f018 100644 --- a/examples/wgpu/wgpu_teapot_camera/shaders/vs.wgsl +++ b/examples/wgpu/wgpu_teapot_camera/shaders/vs.wgsl @@ -1,16 +1,15 @@ -[[block]] struct Data { - world: mat4x4; - view: mat4x4; - proj: mat4x4; + world: mat4x4, + view: mat4x4, + proj: mat4x4, }; struct VertexOutput { - [[location(0)]] normal: vec3; - [[builtin(position)]] pos: vec4; + @location(0) normal: vec3, + @builtin(position) pos: vec4, }; -[[group(0), binding(0)]] +@group(0) @binding(0) var uniforms: Data; fn custom_inverse(m: mat3x3) -> mat3x3 { @@ -29,10 +28,10 @@ fn custom_inverse(m: mat3x3) -> mat3x3 { return minv; } -[[stage(vertex)]] +@vertex fn main( - [[location(0)]] pos: vec3, - [[location(1)]] normal: vec3, + @location(0) pos: vec3, + @location(1) normal: vec3, ) -> VertexOutput { let worldview: mat4x4 = uniforms.view * uniforms.world; let wv3: mat3x3 = mat3x3(worldview[0].xyz, worldview[1].xyz, worldview[2].xyz); diff --git a/examples/wgpu/wgpu_teapot_camera/wgpu_teapot_camera.rs b/examples/wgpu/wgpu_teapot_camera/wgpu_teapot_camera.rs index b36d66293..62f34115d 100644 --- a/examples/wgpu/wgpu_teapot_camera/wgpu_teapot_camera.rs +++ b/examples/wgpu/wgpu_teapot_camera/wgpu_teapot_camera.rs @@ -91,7 +91,9 @@ fn model(app: &App) -> Model { let window = app.window(w_id).unwrap(); let camera_is_active = true; - window.set_cursor_grab(true).unwrap(); + if let Err(e) = window.set_cursor_grab(true) { + eprintln!("warning: cursor grabbing not supported: {e}"); + } window.set_cursor_visible(false); let device = window.device(); let format = Frame::TEXTURE_FORMAT; @@ -100,8 +102,8 @@ fn model(app: &App) -> Model { let vs_desc = wgpu::include_wgsl!("shaders/vs.wgsl"); let fs_desc = wgpu::include_wgsl!("shaders/fs.wgsl"); - let vs_mod = device.create_shader_module(&vs_desc); - let fs_mod = device.create_shader_module(&fs_desc); + let vs_mod = device.create_shader_module(vs_desc); + let fs_mod = device.create_shader_module(fs_desc); // Create the vertex, normal and index buffers. let vertices_bytes = vertices_as_bytes(&data::VERTICES); diff --git a/examples/wgpu/wgpu_triangle/shaders/fs.wgsl b/examples/wgpu/wgpu_triangle/shaders/fs.wgsl index a6f61336e..cf27bb563 100644 --- a/examples/wgpu/wgpu_triangle/shaders/fs.wgsl +++ b/examples/wgpu/wgpu_triangle/shaders/fs.wgsl @@ -1,4 +1,4 @@ -[[stage(fragment)]] -fn main() -> [[location(0)]] vec4 { +@fragment +fn main() -> @location(0) vec4 { return vec4(1.0, 0.0, 0.0, 1.0); } diff --git a/examples/wgpu/wgpu_triangle/shaders/vs.wgsl b/examples/wgpu/wgpu_triangle/shaders/vs.wgsl index 9a30e7c9c..24ec5ee10 100644 --- a/examples/wgpu/wgpu_triangle/shaders/vs.wgsl +++ b/examples/wgpu/wgpu_triangle/shaders/vs.wgsl @@ -1,4 +1,4 @@ -[[stage(vertex)]] -fn main([[location(0)]] pos: vec2) -> [[builtin(position)]] vec4 { +@vertex +fn main(@location(0) pos: vec2) -> @builtin(position) vec4 { return vec4(pos, 0.0, 1.0); } diff --git a/examples/wgpu/wgpu_triangle/wgpu_triangle.rs b/examples/wgpu/wgpu_triangle/wgpu_triangle.rs index 5b48d4d1b..231ee22ed 100644 --- a/examples/wgpu/wgpu_triangle/wgpu_triangle.rs +++ b/examples/wgpu/wgpu_triangle/wgpu_triangle.rs @@ -50,8 +50,8 @@ fn model(app: &App) -> Model { // Load shader modules. let vs_desc = wgpu::include_wgsl!("shaders/vs.wgsl"); let fs_desc = wgpu::include_wgsl!("shaders/fs.wgsl"); - let vs_mod = device.create_shader_module(&vs_desc); - let fs_mod = device.create_shader_module(&fs_desc); + let vs_mod = device.create_shader_module(vs_desc); + let fs_mod = device.create_shader_module(fs_desc); // Create the vertex buffer. let vertices_bytes = vertices_as_bytes(&VERTICES[..]); diff --git a/examples/wgpu/wgpu_triangle_raw_frame/shaders/fs.wgsl b/examples/wgpu/wgpu_triangle_raw_frame/shaders/fs.wgsl index a6f61336e..cf27bb563 100644 --- a/examples/wgpu/wgpu_triangle_raw_frame/shaders/fs.wgsl +++ b/examples/wgpu/wgpu_triangle_raw_frame/shaders/fs.wgsl @@ -1,4 +1,4 @@ -[[stage(fragment)]] -fn main() -> [[location(0)]] vec4 { +@fragment +fn main() -> @location(0) vec4 { return vec4(1.0, 0.0, 0.0, 1.0); } diff --git a/examples/wgpu/wgpu_triangle_raw_frame/shaders/vs.wgsl b/examples/wgpu/wgpu_triangle_raw_frame/shaders/vs.wgsl index 9a30e7c9c..24ec5ee10 100644 --- a/examples/wgpu/wgpu_triangle_raw_frame/shaders/vs.wgsl +++ b/examples/wgpu/wgpu_triangle_raw_frame/shaders/vs.wgsl @@ -1,4 +1,4 @@ -[[stage(vertex)]] -fn main([[location(0)]] pos: vec2) -> [[builtin(position)]] vec4 { +@vertex +fn main(@location(0) pos: vec2) -> @builtin(position) vec4 { return vec4(pos, 0.0, 1.0); } diff --git a/examples/wgpu/wgpu_triangle_raw_frame/wgpu_triangle_raw_frame.rs b/examples/wgpu/wgpu_triangle_raw_frame/wgpu_triangle_raw_frame.rs index 2a4c3e585..390274886 100644 --- a/examples/wgpu/wgpu_triangle_raw_frame/wgpu_triangle_raw_frame.rs +++ b/examples/wgpu/wgpu_triangle_raw_frame/wgpu_triangle_raw_frame.rs @@ -46,8 +46,8 @@ fn model(app: &App) -> Model { let vs_desc = wgpu::include_wgsl!("shaders/vs.wgsl"); let fs_desc = wgpu::include_wgsl!("shaders/fs.wgsl"); - let vs_mod = device.create_shader_module(&vs_desc); - let fs_mod = device.create_shader_module(&fs_desc); + let vs_mod = device.create_shader_module(vs_desc); + let fs_mod = device.create_shader_module(fs_desc); let vertices_bytes = vertices_as_bytes(&VERTICES[..]); let usage = wgpu::BufferUsages::VERTEX; diff --git a/generative_design/image/p_4_3_1_02.rs b/generative_design/image/p_4_3_1_02.rs index 3db1692ca..73247e5da 100644 --- a/generative_design/image/p_4_3_1_02.rs +++ b/generative_design/image/p_4_3_1_02.rs @@ -44,18 +44,14 @@ struct SvgPath { events: Vec, weight: f32, color: Rgba, - width: f32, - height: f32, } impl SvgPath { - fn new(events: Vec, weight: f32, color: Rgba, width: f32, height: f32) -> Self { + fn new(events: Vec, weight: f32, color: Rgba) -> Self { SvgPath { events, weight, color, - width, - height, } } } @@ -95,7 +91,6 @@ fn model(app: &App) -> Model { for asset in assets { let opt = usvg::Options::default(); let rtree = usvg::Tree::from_file(&asset, &opt).unwrap(); - let view_box = rtree.svg_node().view_box; for node in rtree.root().descendants() { if let usvg::NodeKind::Path(ref p) = *node.borrow() { @@ -115,9 +110,7 @@ fn model(app: &App) -> Model { for e in path_events { v.push(e); } - let w = view_box.rect.size().width as f32; - let h = view_box.rect.size().height as f32; - let path = SvgPath::new(v, stroke.width.value() as f32, color, w, h); + let path = SvgPath::new(v, stroke.width.value() as f32, color); shapes.push(path); } } diff --git a/nannou/Cargo.toml b/nannou/Cargo.toml index 3d50152bf..984ab86ac 100644 --- a/nannou/Cargo.toml +++ b/nannou/Cargo.toml @@ -11,7 +11,7 @@ homepage = "https://github.com/nannou-org/nannou" edition = "2018" [dependencies] -async-std = "1.10.0" +futures = "0.3" find_folder = "0.3" getrandom = "0.2.3" image = "0.23" @@ -30,13 +30,18 @@ serde_derive = "1" serde_json = "1" toml = "0.5" walkdir = "2" -web-sys = { version = "0.3.55", optional = true } -wgpu_upstream = { version = "0.11.1", package = "wgpu" } -winit = "0.26" +web-sys = { version = "0.3.64", optional = true } +wgpu_upstream = { version = "0.17.1", package = "wgpu" } +winit = "0.28" + +[target.'cfg(not(target_arch = "wasm32"))'.dependencies] +tokio = { version = "1", features = ["full"]} +[target.'cfg(target_arch = "wasm32")'.dependencies] +tokio = { version = "1", features = ["rt"]} [features] default = ["notosans"] # Enables SPIR-V support in the `wgpu` module. spirv = ["nannou_wgpu/spirv"] # Enables experimental WASM compilation for CI-use only -wasm-experimental = ["getrandom/js", "web-sys", "wgpu_upstream/webgl", "async-std/unstable"] +wasm-experimental = ["getrandom/js", "web-sys", "wgpu_upstream/webgl", "wgpu_upstream/fragile-send-sync-non-atomic-wasm"] diff --git a/nannou/src/app.rs b/nannou/src/app.rs index 6fd899182..17a136f45 100644 --- a/nannou/src/app.rs +++ b/nannou/src/app.rs @@ -27,6 +27,7 @@ use std::sync::atomic::{self, AtomicBool}; use std::sync::Arc; use std::time::Duration; use std::{self, future}; +use wgpu_upstream::InstanceDescriptor; use winit; use winit::event_loop::ControlFlow; @@ -451,7 +452,24 @@ where /// thread as some platforms require that their application event loop and windows are /// initialised on the main thread. pub fn run(self) { - async_std::task::block_on(self.run_async()) + let rt = Self::build_runtime(); + rt.block_on(self.run_async()) + } + + #[cfg(not(target_arch = "wasm32"))] + fn build_runtime() -> tokio::runtime::Runtime { + tokio::runtime::Builder::new_multi_thread() + .enable_all() + .build() + .expect("failed to create tokio runtime") + } + + #[cfg(target_arch = "wasm32")] + fn build_runtime() -> tokio::runtime::Runtime { + tokio::runtime::Builder::new_current_thread() + .enable_all() + .build() + .expect("failed to create tokio runtime") } pub async fn run_async(self) { @@ -637,7 +655,10 @@ impl App { capture_frame_timeout: Option, backends: wgpu::Backends, ) -> Self { - let instance = wgpu::Instance::new(backends); + let instance = wgpu::Instance::new(InstanceDescriptor { + backends, + ..Default::default() + }); let adapters = Default::default(); let windows = RefCell::new(HashMap::new()); let draw = RefCell::new(draw::Draw::default()); @@ -1028,7 +1049,7 @@ impl EventLoopWindowTarget { // This method is solely used during `window::Builder::build` to allow for pub(crate) fn as_ref(&self) -> &winit::event_loop::EventLoopWindowTarget<()> { match *self { - EventLoopWindowTarget::Owned(ref event_loop) => (&**event_loop), + EventLoopWindowTarget::Owned(ref event_loop) => &**event_loop, EventLoopWindowTarget::Pointer(ptr) => { // This cast is safe, assuming that the `App`'s `EventLoopWindowTarget` will only // ever be in the `Pointer` state while the pointer is valid - that is, during the @@ -1125,7 +1146,7 @@ fn run_loop( // TODO: Only request a frame from the user if this redraw was requested following an // update. Otherwise, just use the existing intermediary frame. winit::event::Event::RedrawRequested(window_id) => { - if let Some(model) = model.as_ref() { + if let Some(model) = model.as_mut() { // Retrieve the surface frame and the number of this frame. // NOTE: We avoid mutably borrowing `windows` map any longer than necessary to // avoid restricting users from accessing `windows` during `view`. @@ -1222,7 +1243,7 @@ fn run_loop( let view = view.to_fn_ptr::().expect( "unexpected model argument given to window view function", ); - (*view)(&app, &model, frame); + (*view)(&app, model, frame); } Some(window::View::WithModelRaw(raw_view)) => { let raw_view = raw_view.to_fn_ptr::().expect( diff --git a/nannou/src/draw/renderer/mod.rs b/nannou/src/draw/renderer/mod.rs index 7c978435e..c58284ce8 100644 --- a/nannou/src/draw/renderer/mod.rs +++ b/nannou/src/draw/renderer/mod.rs @@ -82,7 +82,7 @@ pub struct Renderer { glyph_cache_texture: wgpu::Texture, depth_texture: wgpu::Texture, depth_texture_view: wgpu::TextureView, - default_texture: wgpu::Texture, + _default_texture: wgpu::Texture, default_texture_view: wgpu::TextureView, uniform_bind_group_layout: wgpu::BindGroupLayout, uniform_bind_group: wgpu::BindGroup, @@ -387,8 +387,8 @@ impl Renderer { // Load shader modules. let vs_desc = wgpu::include_wgsl!("shaders/vs.wgsl"); let fs_desc = wgpu::include_wgsl!("shaders/fs.wgsl"); - let vs_mod = device.create_shader_module(&vs_desc); - let fs_mod = device.create_shader_module(&fs_desc); + let vs_mod = device.create_shader_module(vs_desc); + let fs_mod = device.create_shader_module(fs_desc); // Create the glyph cache texture. let text_sampler_desc = wgpu::SamplerBuilder::new().into_descriptor(); @@ -462,7 +462,7 @@ impl Renderer { glyph_cache_texture, depth_texture, depth_texture_view, - default_texture, + _default_texture: default_texture, default_texture_view, uniform_bind_group_layout, uniform_bind_group, @@ -1052,7 +1052,9 @@ fn create_text_bind_group_layout(device: &wgpu::Device, filtering: bool) -> wgpu wgpu::ShaderStages::FRAGMENT, false, wgpu::TextureViewDimension::D2, - Renderer::GLYPH_CACHE_TEXTURE_FORMAT.describe().sample_type, + Renderer::GLYPH_CACHE_TEXTURE_FORMAT + .sample_type(None) + .expect("Expected format to have sample type"), ) .build(device) } diff --git a/nannou/src/draw/renderer/shaders/fs.wgsl b/nannou/src/draw/renderer/shaders/fs.wgsl index 5ef4df964..c75a2b6da 100644 --- a/nannou/src/draw/renderer/shaders/fs.wgsl +++ b/nannou/src/draw/renderer/shaders/fs.wgsl @@ -1,21 +1,21 @@ struct FragmentOutput { - [[location(0)]] color: vec4; + @location(0) color: vec4, }; -[[group(1), binding(0)]] +@group(1) @binding(0) var text_sampler: sampler; -[[group(1), binding(1)]] +@group(1) @binding(1) var text: texture_2d; -[[group(2), binding(0)]] +@group(2) @binding(0) var tex_sampler: sampler; -[[group(2), binding(1)]] +@group(2) @binding(1) var tex: texture_2d; -[[stage(fragment)]] +@fragment fn main( - [[location(0)]] color: vec4, - [[location(1)]] tex_coords: vec2, - [[location(2)]] mode: u32, + @location(0) color: vec4, + @location(1) tex_coords: vec2, + @location(2) mode: u32, ) -> FragmentOutput { let tex_color: vec4 = textureSample(tex, tex_sampler, tex_coords); let text_color: vec4 = textureSample(text, text_sampler, tex_coords); diff --git a/nannou/src/draw/renderer/shaders/vs.wgsl b/nannou/src/draw/renderer/shaders/vs.wgsl index c8d8923c0..f50b85a77 100644 --- a/nannou/src/draw/renderer/shaders/vs.wgsl +++ b/nannou/src/draw/renderer/shaders/vs.wgsl @@ -1,24 +1,23 @@ -[[block]] struct Data { - proj: mat4x4; + proj: mat4x4, }; struct VertexOutput { - [[location(0)]] color: vec4; - [[location(1)]] tex_coords: vec2; - [[location(2)]] mode: u32; - [[builtin(position)]] pos: vec4; + @location(0) color: vec4, + @location(1) tex_coords: vec2, + @location(2) mode: u32, + @builtin(position) pos: vec4, }; -[[group(0), binding(0)]] +@group(0) @binding(0) var uniforms: Data; -[[stage(vertex)]] +@vertex fn main( - [[location(0)]] position: vec3, - [[location(1)]] color: vec4, - [[location(2)]] tex_coords: vec2, - [[location(3)]] mode: u32, + @location(0) position: vec3, + @location(1) color: vec4, + @location(2) tex_coords: vec2, + @location(3) mode: u32, ) -> VertexOutput { let out_pos: vec4 = uniforms.proj * vec4(position, 1.0); return VertexOutput(color, tex_coords, mode, out_pos); diff --git a/nannou/src/event.rs b/nannou/src/event.rs index 286230a48..1849bc5ac 100644 --- a/nannou/src/event.rs +++ b/nannou/src/event.rs @@ -307,6 +307,12 @@ impl WindowEvent { | winit::event::WindowEvent::ScaleFactorChanged { .. } => { return None; } + // new 0.28 events + winit::event::WindowEvent::Ime(_) + | winit::event::WindowEvent::TouchpadMagnify { .. } + | winit::event::WindowEvent::SmartMagnify { .. } + | winit::event::WindowEvent::TouchpadRotate { .. } + | winit::event::WindowEvent::Occluded(_) => return None, }; Some(event) diff --git a/nannou/src/window.rs b/nannou/src/window.rs index 81bab37d5..be1695c4a 100644 --- a/nannou/src/window.rs +++ b/nannou/src/window.rs @@ -18,10 +18,14 @@ use std::path::{Path, PathBuf}; use std::sync::Arc; use std::time::Duration; use std::{env, fmt}; +use wgpu_upstream::CompositeAlphaMode; use winit::dpi::{LogicalSize, PhysicalSize}; +#[cfg(target_os = "macos")] +use winit::platform::macos::WindowBuilderExtMacOS; pub use winit::window::Fullscreen; pub use winit::window::WindowId as Id; +use winit::window::{CursorGrabMode, WindowLevel}; /// The default dimensions used for a window in the case that none are specified. pub const DEFAULT_DIMENSIONS: LogicalSize = LogicalSize { @@ -330,7 +334,13 @@ impl SurfaceConfigurationBuilder { let usage = self.usage.unwrap_or(Self::DEFAULT_USAGE); let format = self .format - .or_else(|| surface.get_preferred_format(&adapter)) + .or_else(|| { + surface + .get_capabilities(&adapter) + .formats + .get(0) + .map(|x| x.clone()) + }) .unwrap_or(Self::DEFAULT_FORMAT); let present_mode = self.present_mode.unwrap_or(Self::DEFAULT_PRESENT_MODE); wgpu::SurfaceConfiguration { @@ -339,6 +349,8 @@ impl SurfaceConfigurationBuilder { width: width_px, height: height_px, present_mode, + alpha_mode: CompositeAlphaMode::Auto, + view_formats: Vec::new(), } } } @@ -729,7 +741,9 @@ impl<'app> Builder<'app> { #[cfg(not(target_os = "unknown"))] /// Builds the window, inserts it into the `App`'s display map and returns the unique ID. pub fn build(self) -> Result { - async_std::task::block_on(self.build_async()) + tokio::task::block_in_place(move || { + tokio::runtime::Handle::current().block_on(async move { self.build_async().await }) + }) } pub async fn build_async(self) -> Result { @@ -769,18 +783,32 @@ impl<'app> Builder<'app> { target_os = "netbsd", target_os = "openbsd" ))] + #[cfg(not(feature = "wayland"))] + { + use winit::platform::x11::WindowBuilderExtX11; + window = window.with_name("nannou".to_string(), "nannou".to_string()); + } + + #[cfg(any( + target_os = "linux", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "netbsd", + target_os = "openbsd" + ))] + #[cfg(feature = "wayland")] { - use winit::platform::unix::WindowBuilderExtUnix; - window = window.with_class("nannou".to_string(), "nannou".to_string()); + use winit::platform::wayland::WindowBuilderExtWayland; + window = window.with_name("nannou".to_string(), "nannou".to_string()); } // Set default dimensions in the case that none were given. let initial_window_size = window - .window + .window_attributes() .inner_size .or_else(|| { window - .window + .window_attributes() .fullscreen .as_ref() .and_then(|fullscreen| match fullscreen { @@ -803,7 +831,7 @@ impl<'app> Builder<'app> { }) .unwrap_or_else(|| { let mut dim = DEFAULT_DIMENSIONS; - if let Some(min) = window.window.min_inner_size { + if let Some(min) = window.window_attributes().min_inner_size { match min { winit::dpi::Size::Logical(min) => { dim.width = dim.width.max(min.width as _); @@ -816,7 +844,7 @@ impl<'app> Builder<'app> { } } } - if let Some(max) = window.window.max_inner_size { + if let Some(max) = window.window_attributes().max_inner_size { match max { winit::dpi::Size::Logical(max) => { dim.width = dim.width.min(max.width as _); @@ -834,13 +862,17 @@ impl<'app> Builder<'app> { // Use the `initial_window_size` as the default dimensions for the window if none // were specified. - if window.window.inner_size.is_none() && window.window.fullscreen.is_none() { - window.window.inner_size = Some(initial_window_size); + if window.window_attributes().inner_size.is_none() + && window.window_attributes().fullscreen.is_none() + { + window = window.with_inner_size(initial_window_size); } // Set a default minimum window size for configuring the surface. - if window.window.min_inner_size.is_none() && window.window.fullscreen.is_none() { - window.window.min_inner_size = Some(winit::dpi::Size::Physical(MIN_SC_PIXELS)); + if window.window_attributes().min_inner_size.is_none() + && window.window_attributes().fullscreen.is_none() + { + window = window.with_min_inner_size(winit::dpi::Size::Physical(MIN_SC_PIXELS)); } // Background must be initially cleared @@ -848,7 +880,11 @@ impl<'app> Builder<'app> { let clear_color = clear_color.unwrap_or_else(|| { let mut color: wgpu::Color = Default::default(); - color.a = if window.window.transparent { 0.0 } else { 1.0 }; + color.a = if window.window_attributes().transparent { + 0.0 + } else { + 1.0 + }; color }); @@ -878,7 +914,11 @@ impl<'app> Builder<'app> { } // Build the wgpu surface. - let surface = unsafe { app.instance().create_surface(&window) }; + let surface = unsafe { + app.instance() + .create_surface(&window) + .expect("Could not create surface") + }; // Request the adapter. let request_adapter_opts = wgpu::RequestAdapterOptions { @@ -1071,7 +1111,13 @@ impl<'app> Builder<'app> { /// Sets whether or not the window will always be on top of other windows. pub fn always_on_top(self, always_on_top: bool) -> Self { - self.map_window(|w| w.with_always_on_top(always_on_top)) + self.map_window(|w| { + w.with_window_level(if always_on_top { + WindowLevel::AlwaysOnBottom + } else { + WindowLevel::Normal + }) + }) } /// Sets the window icon. @@ -1315,7 +1361,11 @@ impl Window { /// Change whether or not the window will always be on top of other windows. pub fn set_always_on_top(&self, always_on_top: bool) { - self.window.set_always_on_top(always_on_top) + self.window.set_window_level(if always_on_top { + WindowLevel::AlwaysOnTop + } else { + WindowLevel::Normal + }) } /// Sets the window icon. On Windows and X11, this is typically the small icon in the top-left @@ -1380,7 +1430,11 @@ impl Window { /// - **iOS:** Always returns an Err. /// - **Web:** Has no effect. pub fn set_cursor_grab(&self, grab: bool) -> Result<(), winit::error::ExternalError> { - self.window.set_cursor_grab(grab) + self.window.set_cursor_grab(if grab { + CursorGrabMode::Locked + } else { + CursorGrabMode::None + }) } /// Set the cursor's visibility. diff --git a/nannou_egui/Cargo.toml b/nannou_egui/Cargo.toml index b2776bff2..680601c8f 100644 --- a/nannou_egui/Cargo.toml +++ b/nannou_egui/Cargo.toml @@ -12,7 +12,10 @@ repository = "https://github.com/AlexEne/nannou_egui" readme = "../README.md" [dependencies] -egui_wgpu_backend = "0.14" -egui = "0.15.0" -winit = "0.26" +egui-wgpu = "0.23" +egui = "0.23" +winit = "0.28" nannou = { version = "0.18.1", path = "../nannou" } + +[features] +wayland = [] \ No newline at end of file diff --git a/nannou_egui/src/lib.rs b/nannou_egui/src/lib.rs index cefdc1b8b..d0e39971c 100644 --- a/nannou_egui/src/lib.rs +++ b/nannou_egui/src/lib.rs @@ -1,16 +1,12 @@ pub use egui; pub use egui::color_picker; -pub use egui_wgpu_backend; +pub use egui_wgpu; -use egui::{pos2, ClippedMesh, CtxRef}; -use egui_wgpu_backend::{epi, ScreenDescriptor}; +use egui::{pos2, ClippedPrimitive, PlatformOutput}; +use egui_wgpu::renderer::ScreenDescriptor; +use nannou::wgpu::ToTextureView; use nannou::{wgpu, winit::event::VirtualKeyCode, winit::event::WindowEvent::*}; -use std::{ - cell::RefCell, - ops::Deref, - sync::{Arc, Mutex}, - time::Duration, -}; +use std::{cell::RefCell, ops::Deref, time::Duration}; /// All `egui`-related state for a single window. /// @@ -18,7 +14,7 @@ use std::{ /// /// For multi-window user interfaces, you will need to create an instance of this type per-window. pub struct Egui { - context: CtxRef, + context: egui::Context, renderer: RefCell, input: Input, } @@ -28,8 +24,9 @@ pub struct Egui { /// /// For targeting more than one window, users should construct a `Egui` for each. pub struct Renderer { - render_pass: egui_wgpu_backend::RenderPass, - paint_jobs: Vec, + renderer: egui_wgpu::Renderer, + paint_jobs: Vec, + textures_delta: egui::TexturesDelta, } /// Tracking user and application event input. @@ -49,8 +46,6 @@ pub struct FrameCtx<'a> { ended: bool, } -struct RepaintSignal(Mutex); - impl Egui { /// Construct the `Egui` from its parts. /// @@ -89,7 +84,7 @@ impl Egui { } /// Access to the inner `egui::CtxRef`. - pub fn ctx(&self) -> &CtxRef { + pub fn ctx(&self) -> &egui::Context { &self.context } @@ -116,6 +111,10 @@ impl Egui { FrameCtx { ui, ended } } + pub fn end_frame(&mut self) -> PlatformOutput { + self.end_frame_inner() + } + /// Registers a wgpu::Texture with a egui::TextureId. pub fn texture_from_wgpu_texture( &mut self, @@ -123,10 +122,11 @@ impl Egui { texture: &wgpu::Texture, texture_filter: wgpu::FilterMode, ) -> egui::TextureId { - self.renderer - .borrow_mut() - .render_pass - .egui_texture_from_wgpu_texture(device, texture, texture_filter) + self.renderer.borrow_mut().renderer.register_native_texture( + device, + &texture.to_texture_view(), + texture_filter, + ) } /// Registers a wgpu::Texture with an existing egui::TextureId. @@ -136,79 +136,39 @@ impl Egui { texture: &wgpu::Texture, texture_filter: wgpu::FilterMode, id: egui::TextureId, - ) -> Result<(), egui_wgpu_backend::BackendError> { + ) -> Result<(), egui_wgpu::WgpuError> { self.renderer .borrow_mut() - .render_pass - .update_egui_texture_from_wgpu_texture(device, texture, texture_filter, id) + .renderer + .update_egui_texture_from_wgpu_texture( + device, + &texture.to_texture_view(), + texture_filter, + id, + ); + Ok(()) } /// Draws the contents of the inner `context` to the given frame. - pub fn draw_to_frame( - &self, - frame: &nannou::Frame, - ) -> Result<(), egui_wgpu_backend::BackendError> { + pub fn draw_to_frame(&self, frame: &nannou::Frame) -> Result<(), egui_wgpu::WgpuError> { let mut renderer = self.renderer.borrow_mut(); - renderer.draw_to_frame(&self.context, frame) - } - - /// Provide access to an `epi::Frame` within the given function. - /// - /// This method is primarily used for apps based on the `epi` interface. - pub fn with_epi_frame(&mut self, proxy: nannou::app::Proxy, f: F) - where - F: FnOnce(&CtxRef, &mut epi::Frame), - { - let mut renderer = self.renderer.borrow_mut(); - let integration_info = epi::IntegrationInfo { - native_pixels_per_point: Some(self.input.window_scale_factor as _), - // TODO: Provide access to this stuff. - web_info: None, - prefer_dark_mode: None, - cpu_usage: None, - name: "egui_nannou_wgpu", - }; - let mut app_output = epi::backend::AppOutput::default(); - let repaint_signal = Arc::new(RepaintSignal(Mutex::new(proxy))); - let mut frame = epi::backend::FrameBuilder { - info: integration_info, - tex_allocator: &mut renderer.render_pass, - // TODO: We may want to support a http feature for hyperlinks? - // #[cfg(feature = "http")] - // http: http.clone(), - output: &mut app_output, - repaint_signal: repaint_signal as Arc<_>, - } - .build(); - f(&self.context, &mut frame) - } - - /// The same as `with_epi_frame`, but calls `begin_frame` before calling the given function, - /// and then calls `end_frame` before returning. - pub fn do_frame_with_epi_frame(&mut self, proxy: nannou::app::Proxy, f: F) -> egui::Output - where - F: FnOnce(&CtxRef, &mut epi::Frame), - { - self.begin_frame_inner(); - self.with_epi_frame(proxy.clone(), f); - let output = self.end_frame_inner(); - - // If a repaint is required, ensure the event loop emits another update. - if output.needs_repaint { - proxy.wakeup().unwrap(); - } - - output + renderer.draw_to_frame(frame) } fn begin_frame_inner(&mut self) { self.context.begin_frame(self.input.raw.take()); } - fn end_frame_inner(&mut self) -> egui::Output { - let (output, paint_cmds) = self.context.end_frame(); - self.renderer.borrow_mut().paint_jobs = self.context.tessellate(paint_cmds); - output + fn end_frame_inner(&mut self) -> egui::PlatformOutput { + let egui::FullOutput { + shapes, + platform_output, + textures_delta, + .. + } = self.context.end_frame(); + self.renderer.borrow_mut().paint_jobs = self.context.tessellate(shapes); + self.renderer.borrow_mut().textures_delta = textures_delta; + platform_output } } @@ -267,11 +227,16 @@ impl Input { match delta { winit::event::MouseScrollDelta::LineDelta(x, y) => { let line_height = 24.0; - self.raw.scroll_delta = egui::vec2(*x, *y) * line_height; + self.raw + .events + .push(egui::Event::Scroll(egui::vec2(*x, *y) * line_height)); } winit::event::MouseScrollDelta::PixelDelta(delta) => { // Actually point delta - self.raw.scroll_delta = egui::vec2(delta.x as f32, delta.y as f32); + self.raw.events.push(egui::Event::Scroll(egui::vec2( + delta.x as f32, + delta.y as f32, + ))); } } } @@ -297,6 +262,7 @@ impl Input { self.raw.events.push(egui::Event::Key { key, pressed: input.state == winit::event::ElementState::Pressed, + repeat: false, modifiers: self.raw.modifiers, }); } @@ -340,12 +306,9 @@ impl Renderer { target_msaa_samples: u32, ) -> Self { Self { - render_pass: egui_wgpu_backend::RenderPass::new( - device, - target_format, - target_msaa_samples, - ), + renderer: egui_wgpu::Renderer::new(device, target_format, None, target_msaa_samples), paint_jobs: Vec::new(), + textures_delta: Default::default(), } } @@ -360,34 +323,42 @@ impl Renderer { /// Encode a render pass for drawing the given context's texture to the given `dst_texture`. pub fn encode_render_pass( &mut self, - context: &CtxRef, device: &wgpu::Device, queue: &wgpu::Queue, encoder: &mut wgpu::CommandEncoder, dst_size_pixels: [u32; 2], dst_scale_factor: f32, dst_texture: &wgpu::TextureView, - ) -> Result<(), egui_wgpu_backend::BackendError> { - let render_pass = &mut self.render_pass; + ) -> Result<(), egui_wgpu::WgpuError> { + let renderer = &mut self.renderer; + let textures = &self.textures_delta; let paint_jobs = &self.paint_jobs; - let [physical_width, physical_height] = dst_size_pixels; let screen_descriptor = ScreenDescriptor { - physical_width, - physical_height, - scale_factor: dst_scale_factor, + size_in_pixels: dst_size_pixels, + pixels_per_point: dst_scale_factor, }; - render_pass.update_texture(device, queue, &*context.texture()); - render_pass.update_user_textures(&device, &queue); - render_pass.update_buffers(device, queue, &paint_jobs, &screen_descriptor); - render_pass.execute(encoder, dst_texture, &paint_jobs, &screen_descriptor, None) + for (id, image_delta) in &textures.set { + renderer.update_texture(&device, &queue, *id, &image_delta); + } + renderer.update_buffers(device, queue, encoder, &paint_jobs, &screen_descriptor); + let mut render_pass = encoder.begin_render_pass(&egui_wgpu::wgpu::RenderPassDescriptor { + label: Some("nannou_egui_render_pass"), + color_attachments: &[Some(egui_wgpu::wgpu::RenderPassColorAttachment { + view: &dst_texture, + resolve_target: None, + ops: egui_wgpu::wgpu::Operations { + load: egui_wgpu::wgpu::LoadOp::Load, + store: true, + }, + })], + depth_stencil_attachment: None, + }); + renderer.render(&mut render_pass, &paint_jobs, &screen_descriptor); + Ok(()) } /// Encodes a render pass for drawing the given context's texture to the given frame. - pub fn draw_to_frame( - &mut self, - context: &CtxRef, - frame: &nannou::Frame, - ) -> Result<(), egui_wgpu_backend::BackendError> { + pub fn draw_to_frame(&mut self, frame: &nannou::Frame) -> Result<(), egui_wgpu::WgpuError> { let device_queue_pair = frame.device_queue_pair(); let device = device_queue_pair.device(); let queue = device_queue_pair.queue(); @@ -397,7 +368,6 @@ impl Renderer { let texture_view = frame.texture_view(); let mut encoder = frame.command_encoder(); self.encode_render_pass( - context, device, queue, &mut encoder, @@ -410,7 +380,7 @@ impl Renderer { impl<'a> FrameCtx<'a> { /// Produces a `CtxRef` ready for describing the UI for this frame. - pub fn context(&self) -> CtxRef { + pub fn context(&self) -> egui::Context { self.ui.context.clone() } @@ -435,20 +405,12 @@ impl<'a> Drop for FrameCtx<'a> { } impl<'a> Deref for FrameCtx<'a> { - type Target = egui::CtxRef; + type Target = egui::Context; fn deref(&self) -> &Self::Target { &self.ui.context } } -impl epi::RepaintSignal for RepaintSignal { - fn request_repaint(&self) { - if let Ok(guard) = self.0.lock() { - guard.wakeup().ok(); - } - } -} - /// Translates winit to egui keycodes. #[inline] fn winit_to_egui_key_code(key: VirtualKeyCode) -> Option { diff --git a/nannou_egui_demo_app/Cargo.toml b/nannou_egui_demo_app/Cargo.toml index cf12f3769..60cb783a5 100644 --- a/nannou_egui_demo_app/Cargo.toml +++ b/nannou_egui_demo_app/Cargo.toml @@ -8,4 +8,4 @@ publish = false [dependencies] nannou_egui = { version = "0.5", path = "../nannou_egui" } nannou = { version = "0.18.1", path = "../nannou" } -egui_demo_lib = "0.15" +egui_demo_lib = "0.23" diff --git a/nannou_egui_demo_app/src/main.rs b/nannou_egui_demo_app/src/main.rs index 7c91a4a5c..8d5a447eb 100644 --- a/nannou_egui_demo_app/src/main.rs +++ b/nannou_egui_demo_app/src/main.rs @@ -1,5 +1,6 @@ use nannou::prelude::*; -use nannou_egui::{egui_wgpu_backend::epi::App as EguiApp, Egui}; +use nannou_egui::Egui; +use std::sync::{Arc, Mutex}; fn main() { nannou::app(model).update(update).run(); @@ -7,7 +8,7 @@ fn main() { struct Model { egui: Egui, - egui_demo_app: egui_demo_lib::WrapApp, + egui_demo_app: egui_demo_lib::DemoWindows, } fn model(app: &App) -> Model { @@ -19,11 +20,12 @@ fn model(app: &App) -> Model { .build() .unwrap(); let window = app.window(w_id).unwrap(); - let mut egui = Egui::from_window(&window); - let mut egui_demo_app = egui_demo_lib::WrapApp::default(); - let proxy = app.create_proxy(); - egui.do_frame_with_epi_frame(proxy, |ctx, epi_frame| { - egui_demo_app.setup(&ctx, epi_frame, None); + let egui = Egui::from_window(&window); + let egui_demo_app = egui_demo_lib::DemoWindows::default(); + + let proxy = Arc::new(Mutex::new(app.create_proxy())); + egui.ctx().set_request_repaint_callback(move |_| { + proxy.lock().unwrap().wakeup().unwrap(); }); Model { egui, @@ -35,19 +37,19 @@ fn raw_window_event(_app: &App, model: &mut Model, event: &nannou::winit::event: model.egui.handle_raw_event(event); } -fn update(app: &App, model: &mut Model, update: Update) { +fn update(_app: &App, model: &mut Model, update: Update) { let Model { ref mut egui, ref mut egui_demo_app, .. } = *model; egui.set_elapsed_time(update.since_start); - let proxy = app.create_proxy(); - egui.do_frame_with_epi_frame(proxy, |ctx, frame| { - egui_demo_app.update(&ctx, frame); - }); + let ctx = egui.begin_frame(); + egui_demo_app.ui(&ctx.context()); + let _ = ctx.end(); } fn view(_app: &App, model: &Model, frame: Frame) { + frame.clear(BLACK); model.egui.draw_to_frame(&frame).unwrap(); } diff --git a/nannou_laser/src/ffi.rs b/nannou_laser/src/ffi.rs index f059ced3b..e87398e4b 100644 --- a/nannou_laser/src/ffi.rs +++ b/nannou_laser/src/ffi.rs @@ -848,7 +848,7 @@ pub unsafe extern "C" fn raw_string_ref(msg: *const RawString) -> *const raw::c_ #[no_mangle] pub unsafe extern "C" fn raw_string_drop(msg: RawString) { if msg.inner != std::ptr::null_mut() { - CString::from_raw(msg.inner); + std::mem::drop(CString::from_raw(msg.inner)); } } @@ -856,7 +856,7 @@ pub unsafe extern "C" fn raw_string_drop(msg: RawString) { #[no_mangle] pub unsafe extern "C" fn frame_stream_drop(stream: FrameStream) { if stream.inner != std::ptr::null_mut() { - Box::from_raw(stream.inner); + std::mem::drop(Box::from_raw(stream.inner)); } } @@ -864,7 +864,7 @@ pub unsafe extern "C" fn frame_stream_drop(stream: FrameStream) { #[no_mangle] pub unsafe extern "C" fn raw_stream_drop(stream: RawStream) { if stream.inner != std::ptr::null_mut() { - Box::from_raw(stream.inner); + std::mem::drop(Box::from_raw(stream.inner)); } } @@ -872,7 +872,7 @@ pub unsafe extern "C" fn raw_stream_drop(stream: RawStream) { #[no_mangle] pub unsafe extern "C" fn detect_dacs_async_drop(detect: DetectDacsAsync) { if detect.inner != std::ptr::null_mut() { - Box::from_raw(detect.inner); + std::mem::drop(Box::from_raw(detect.inner)); } } @@ -880,7 +880,7 @@ pub unsafe extern "C" fn detect_dacs_async_drop(detect: DetectDacsAsync) { #[no_mangle] pub unsafe extern "C" fn api_drop(api: Api) { if api.inner != std::ptr::null_mut() { - Box::from_raw(api.inner); + std::mem::drop(Box::from_raw(api.inner)); } } diff --git a/nannou_wgpu/Cargo.toml b/nannou_wgpu/Cargo.toml index a2057ca71..a441ea97e 100644 --- a/nannou_wgpu/Cargo.toml +++ b/nannou_wgpu/Cargo.toml @@ -10,11 +10,16 @@ homepage = "https://nannou.cc" edition = "2018" [dependencies] -async-std = "1.10.0" +futures = "0.3" image = { version = "0.23", optional = true } instant = { version = "0.1.9", optional = true } num_cpus = { version = "1", optional = true } -wgpu_upstream = { version = "0.11.1", package = "wgpu" } +wgpu_upstream = { version = "0.17.1", package = "wgpu" } + +[target.'cfg(not(target_arch = "wasm32"))'.dependencies] +tokio = { version = "1", features = ["full"]} +[target.'cfg(target_arch = "wasm32")'.dependencies] +tokio = { version = "1", features = ["rt"]} [features] capturer = ["image", "instant", "num_cpus"] diff --git a/nannou_wgpu/src/bind_group_builder.rs b/nannou_wgpu/src/bind_group_builder.rs index 233a36d03..97a788149 100644 --- a/nannou_wgpu/src/bind_group_builder.rs +++ b/nannou_wgpu/src/bind_group_builder.rs @@ -1,4 +1,4 @@ -use wgpu_upstream::BufferBinding; +use wgpu_upstream::{BufferBinding, SamplerBindingType}; use crate as wgpu; @@ -60,21 +60,17 @@ impl LayoutBuilder { /// Add a sampler binding to the layout. pub fn sampler(self, visibility: wgpu::ShaderStages, filtering: bool) -> Self { - let comparison = false; - let ty = wgpu::BindingType::Sampler { - filtering, - comparison, - }; + let ty = wgpu::BindingType::Sampler(if filtering { + SamplerBindingType::Filtering + } else { + SamplerBindingType::NonFiltering + }); self.binding(visibility, ty) } /// Add a sampler binding to the layout. - pub fn comparison_sampler(self, visibility: wgpu::ShaderStages, filtering: bool) -> Self { - let comparison = true; - let ty = wgpu::BindingType::Sampler { - filtering, - comparison, - }; + pub fn comparison_sampler(self, visibility: wgpu::ShaderStages) -> Self { + let ty = wgpu::BindingType::Sampler(SamplerBindingType::Comparison); self.binding(visibility, ty) } @@ -86,6 +82,16 @@ impl LayoutBuilder { view_dimension: wgpu::TextureViewDimension, sample_type: wgpu::TextureSampleType, ) -> Self { + // fix sample type in certain scenarios (constraint given by wgpu) + let sample_type = if multisampled + && matches!( + sample_type, + wgpu::TextureSampleType::Float { filterable: true } + ) { + wgpu::TextureSampleType::Float { filterable: false } + } else { + sample_type + }; let ty = wgpu::BindingType::Texture { multisampled, view_dimension, diff --git a/nannou_wgpu/src/device_map.rs b/nannou_wgpu/src/device_map.rs index 77b962127..c4373909b 100644 --- a/nannou_wgpu/src/device_map.rs +++ b/nannou_wgpu/src/device_map.rs @@ -75,7 +75,8 @@ impl AdapterMap { options: wgpu::RequestAdapterOptions<'b>, instance: &'a wgpu::Instance, ) -> Option> { - async_std::task::block_on(self.get_or_request_async(options, instance)) + let rt = tokio::runtime::Handle::current(); + rt.block_on(self.get_or_request_async(options, instance)) } #[cfg(not(target_os = "unknown"))] @@ -91,7 +92,8 @@ impl AdapterMap { options: wgpu::RequestAdapterOptions<'b>, instance: &'a wgpu::Instance, ) -> Option> { - async_std::task::block_on(self.request_async(options, instance)) + let rt = tokio::runtime::Handle::current(); + rt.block_on(self.request_async(options, instance)) } /// The async implementation of `get_or_request`. @@ -163,7 +165,7 @@ impl AdapterMap { .lock() .expect("failed to acquire `AdapterMap` lock"); for adapter in map.values() { - adapter._poll_all_devices(maintain); + adapter._poll_all_devices(maintain.clone()); // TODO: clone? } } } @@ -178,7 +180,8 @@ impl ActiveAdapter { &self, descriptor: wgpu::DeviceDescriptor<'static>, ) -> Arc { - async_std::task::block_on(self.get_or_request_device_async(descriptor)) + let rt = tokio::runtime::Handle::current(); + rt.block_on(self.get_or_request_device_async(descriptor)) } #[cfg(not(target_os = "unknown"))] @@ -191,7 +194,8 @@ impl ActiveAdapter { &self, descriptor: wgpu::DeviceDescriptor<'static>, ) -> Arc { - async_std::task::block_on(self.request_device_async(descriptor)) + let rt = tokio::runtime::Handle::current(); + rt.block_on(self.request_device_async(descriptor)) } /// Check for a device with the given descriptor or request one. @@ -277,7 +281,7 @@ impl ActiveAdapter { .expect("failed to acquire `DeviceMap` lock"); for weak in map.values() { if let Some(pair) = weak.upgrade() { - pair.device().poll(maintain); + pair.device().poll(maintain.clone()); // TODO: clone? } } } diff --git a/nannou_wgpu/src/lib.rs b/nannou_wgpu/src/lib.rs index b2bbe29af..a9b2f9f7f 100644 --- a/nannou_wgpu/src/lib.rs +++ b/nannou_wgpu/src/lib.rs @@ -117,7 +117,7 @@ pub fn shader_from_spirv_bytes( label: Some("nannou_shader_module"), source, }; - device.create_shader_module(&desc) + device.create_shader_module(desc) } /// Adds a simple render pass command to the given encoder that simply clears the given texture diff --git a/nannou_wgpu/src/render_pass.rs b/nannou_wgpu/src/render_pass.rs index 2771fadf0..d69f2597e 100644 --- a/nannou_wgpu/src/render_pass.rs +++ b/nannou_wgpu/src/render_pass.rs @@ -3,7 +3,7 @@ use crate::{self as wgpu, Color, LoadOp}; /// A builder type to simplify the process of creating a render pass descriptor. #[derive(Debug, Default)] pub struct Builder<'a> { - color_attachments: Vec>, + color_attachments: Vec>>, depth_stencil_attachment: Option>, } @@ -168,7 +168,7 @@ impl<'a> Builder<'a> { { let builder = ColorAttachmentDescriptorBuilder::new(attachment); let descriptor = color_builder(builder).descriptor; - self.color_attachments.push(descriptor); + self.color_attachments.push(Some(descriptor)); self } @@ -196,7 +196,7 @@ impl<'a> Builder<'a> { pub fn into_inner( self, ) -> ( - Vec>, + Vec>>, Option>, ) { let Builder { diff --git a/nannou_wgpu/src/render_pipeline_builder.rs b/nannou_wgpu/src/render_pipeline_builder.rs index cf9d97169..b4f1ce0f8 100644 --- a/nannou_wgpu/src/render_pipeline_builder.rs +++ b/nannou_wgpu/src/render_pipeline_builder.rs @@ -30,7 +30,7 @@ pub struct RenderPipelineBuilder<'a> { fs_entry_point: &'a str, primitive: wgpu::PrimitiveState, color_state: Option, - color_states: &'a [wgpu::ColorTargetState], + color_states: &'a [Option], depth_stencil: Option, vertex_buffers: Vec>, multisample: wgpu::MultisampleState, @@ -52,7 +52,7 @@ impl<'a> RenderPipelineBuilder<'a> { front_face: Self::DEFAULT_FRONT_FACE, cull_mode: Self::DEFAULT_CULL_MODE, polygon_mode: Self::DEFAULT_POLYGON_MODE, - clamp_depth: Self::DEFAULT_CLAMP_DEPTH, + unclipped_depth: Self::DEFAULT_UNCLIPPED_DEPTH, conservative: false, }; @@ -101,7 +101,7 @@ impl<'a> RenderPipelineBuilder<'a> { slope_scale: Self::DEFAULT_DEPTH_BIAS_SLOPE_SCALE, clamp: Self::DEFAULT_DEPTH_BIAS_CLAMP, }; - pub const DEFAULT_CLAMP_DEPTH: bool = false; + pub const DEFAULT_UNCLIPPED_DEPTH: bool = false; pub const DEFAULT_DEPTH_STENCIL: wgpu::DepthStencilState = wgpu::DepthStencilState { format: Self::DEFAULT_DEPTH_FORMAT, depth_write_enabled: Self::DEFAULT_DEPTH_WRITE_ENABLED, @@ -387,9 +387,9 @@ impl<'a> RenderPipelineBuilder<'a> { /// If enabled polygon depth is clamped to 0-1 range instead of being clipped. /// - /// Requires `Features::DEPTH_CLAMPING` enabled. - pub fn clamp_depth(mut self, b: bool) -> Self { - self.primitive.clamp_depth = b; + /// Requires `Features::DEPTH_CLIP_CONTROL` enabled. + pub fn unclipped_depth(mut self, b: bool) -> Self { + self.primitive.unclipped_depth = b; self } @@ -527,10 +527,10 @@ fn build( buffers: &vertex_buffers[..], }; - let mut single_color_state = [RenderPipelineBuilder::DEFAULT_COLOR_STATE]; + let mut single_color_state = [Some(RenderPipelineBuilder::DEFAULT_COLOR_STATE)]; let color_states = match (fs_mod.is_some(), color_states.is_empty()) { (true, true) => { - if let Some(cs) = color_state { + if let cs @ Some(_) = color_state { single_color_state[0] = cs; } &single_color_state[..] @@ -559,6 +559,7 @@ fn build( depth_stencil, multisample, fragment, + multiview: None, }; device.create_render_pipeline(&pipeline_desc) diff --git a/nannou_wgpu/src/sampler_builder.rs b/nannou_wgpu/src/sampler_builder.rs index 9d3ca423b..d5514e406 100644 --- a/nannou_wgpu/src/sampler_builder.rs +++ b/nannou_wgpu/src/sampler_builder.rs @@ -1,5 +1,3 @@ -use std::num::NonZeroU8; - use crate as wgpu; /// Simplifies the construction of a `Sampler` with a set of reasonable defaults. @@ -15,10 +13,10 @@ impl<'b> SamplerBuilder { pub const DEFAULT_MAG_FILTER: wgpu::FilterMode = wgpu::FilterMode::Linear; pub const DEFAULT_MIN_FILTER: wgpu::FilterMode = wgpu::FilterMode::Linear; pub const DEFAULT_MIPMAP_FILTER: wgpu::FilterMode = wgpu::FilterMode::Nearest; - pub const DEFAULT_LOD_MIN_CLAMP: f32 = -100.0; + pub const DEFAULT_LOD_MIN_CLAMP: f32 = 0.0; pub const DEFAULT_LOD_MAX_CLAMP: f32 = 100.0; pub const DEFAULT_COMPARE: Option = None; - pub const DEFAULT_ANISOTROPY_CLAMP: Option = None; + pub const DEFAULT_ANISOTROPY_CLAMP: u16 = 1; pub const DEFAULT_LABEL: &'static str = "nannou-sampler"; pub const DEFAULT_BORDER_COLOR: Option = None; pub const DEFAULT_DESCRIPTOR: wgpu::SamplerDescriptor<'static> = wgpu::SamplerDescriptor { @@ -111,7 +109,7 @@ impl<'b> SamplerBuilder { } /// The anisotropy level to clamp to, if any. - pub fn anisotropy_clamp(mut self, clamp: Option) -> Self { + pub fn anisotropy_clamp(mut self, clamp: u16) -> Self { self.descriptor.anisotropy_clamp = clamp; self } diff --git a/nannou_wgpu/src/texture/capturer.rs b/nannou_wgpu/src/texture/capturer.rs index 0ba88ad43..9ed8b76a3 100644 --- a/nannou_wgpu/src/texture/capturer.rs +++ b/nannou_wgpu/src/texture/capturer.rs @@ -91,11 +91,7 @@ impl ThreadPool { active_futures.fetch_sub(1, atomic::Ordering::SeqCst); }; - #[cfg(not(target_os = "unknown"))] - async_std::task::spawn(future); - #[cfg(target_os = "unknown")] - async_std::task::spawn_local(future); - + tokio::spawn(future); Ok(()) } diff --git a/nannou_wgpu/src/texture/image.rs b/nannou_wgpu/src/texture/image.rs index 0c050b676..95eb1de4e 100644 --- a/nannou_wgpu/src/texture/image.rs +++ b/nannou_wgpu/src/texture/image.rs @@ -311,7 +311,14 @@ impl wgpu::RowPaddedBuffer { /// polled. You should *not* rely on the being ready immediately. pub async fn read<'b>(&'b self) -> Result, wgpu::BufferAsyncError> { let slice = self.buffer.slice(..); - slice.map_async(wgpu::MapMode::Read).await?; + let (tx, rx) = futures::channel::oneshot::channel(); + + slice.map_async(wgpu::MapMode::Read, |res| { + tx.send(res).expect("Failed to send map_async result"); + }); + + rx.await.expect("Failed to receive map_async result")?; + Ok(wgpu::ImageReadMapping { buffer: self, // fun exercise: @@ -566,11 +573,13 @@ where // Describe the layout of the data. let extent = texture.extent(); let format = texture.format(); - let block_size = format.describe().block_size; + let block_size = format + .block_size(None) + .expect("Expected the format to have a block size"); let bytes_per_row = extent.width * block_size as u32; let image_data_layout = wgpu::ImageDataLayout { offset: 0, - bytes_per_row: std::num::NonZeroU32::new(bytes_per_row), + bytes_per_row: Some(bytes_per_row), rows_per_image: None, }; @@ -626,12 +635,14 @@ where // Describe the layout of the data. let format = texture.format(); - let block_size = format.describe().block_size; + let block_size = format + .block_size(None) + .expect("Expected the format to have a block size"); let bytes_per_row = extent.width * block_size as u32; let image_data_layout = wgpu::ImageDataLayout { offset: 0, - bytes_per_row: std::num::NonZeroU32::new(bytes_per_row), - rows_per_image: std::num::NonZeroU32::new(height), + bytes_per_row: Some(bytes_per_row), + rows_per_image: Some(height), }; // Collect the data into a single slice. diff --git a/nannou_wgpu/src/texture/mod.rs b/nannou_wgpu/src/texture/mod.rs index 4b943284b..74495af28 100644 --- a/nannou_wgpu/src/texture/mod.rs +++ b/nannou_wgpu/src/texture/mod.rs @@ -2,8 +2,6 @@ use crate::{self as wgpu, RowPaddedBuffer, TextureHandle, TextureViewHandle}; use std::ops::Deref; use std::sync::Arc; -use std::num::NonZeroU32; - #[cfg(feature = "capturer")] pub mod capturer; #[cfg(feature = "image")] @@ -72,14 +70,14 @@ pub struct TextureViewInfo { /// If `Some`, base_mip_level + count must be less or equal to underlying texture mip count. /// /// If `None`, considered to include the rest of the mipmap levels, but at least 1 in total. - pub level_count: Option, + pub level_count: Option, pub base_array_layer: u32, /// Layer count. /// /// If `Some`, base_array_layer + count must be less or equal to the underlying array count. /// /// If `None`, considered to include the rest of the array layers, but at least 1 in total. - pub array_layer_count: Option, + pub array_layer_count: Option, } /// A unique identifier associated with a **Texture**. @@ -177,7 +175,9 @@ impl Texture { /// The component type associated with the texture's format. pub fn sample_type(&self) -> wgpu::TextureSampleType { - self.format().describe().sample_type + self.format() + .sample_type(None) + .expect("Expected the format to have a sample type") } // Custom constructors. @@ -242,9 +242,9 @@ impl Texture { dimension: self.view_dimension(), aspect: infer_aspect_from_format(format), base_mip_level: 0, - level_count: NonZeroU32::new(self.mip_level_count()), + level_count: Some(self.mip_level_count()), base_array_layer: 0, - array_layer_count: NonZeroU32::new(1), + array_layer_count: Some(1), } } @@ -361,7 +361,7 @@ impl TextureView { self.info.base_mip_level } - pub fn level_count(&self) -> Option { + pub fn level_count(&self) -> Option { self.info.level_count } @@ -369,12 +369,14 @@ impl TextureView { self.info.base_array_layer } - pub fn array_layer_count(&self) -> Option { + pub fn array_layer_count(&self) -> Option { self.info.array_layer_count } pub fn sample_type(&self) -> wgpu::TextureSampleType { - self.format().describe().sample_type + self.format() + .sample_type(None) + .expect("Expected the format to have a sample type") } pub fn id(&self) -> TextureViewId { @@ -432,6 +434,7 @@ impl Builder { dimension: Self::DEFAULT_DIMENSION, format: Self::DEFAULT_FORMAT, usage: Self::DEFAULT_USAGE, + view_formats: &[], }; /// Creates a new `Default` builder @@ -583,7 +586,7 @@ impl<'a> ViewBuilder<'a> { /// If `Some`, base_mip_level + count must be less or equal to underlying texture mip count. /// /// If `None`, considered to include the rest of the mipmap levels, but at least 1 in total. - pub fn level_count(mut self, level_count: Option) -> Self { + pub fn level_count(mut self, level_count: Option) -> Self { self.info.level_count = level_count; self } @@ -598,8 +601,8 @@ impl<'a> ViewBuilder<'a> { /// If `Some`, base_array_layer + count must be less or equal to the underlying array count. /// /// If `None`, considered to include the rest of the array layers, but at least 1 in total. - pub fn array_layer_count(mut self, array_layer_count: Option) -> Self { - match (self.info.dimension, array_layer_count.map(|n| n.get())) { + pub fn array_layer_count(mut self, array_layer_count: Option) -> Self { + match (self.info.dimension, array_layer_count) { (wgpu::TextureViewDimension::D2Array, Some(1)) => { self.info.dimension = wgpu::TextureViewDimension::D2; } @@ -619,8 +622,7 @@ impl<'a> ViewBuilder<'a> { /// .array_layer_count(1) /// ``` pub fn layer(self, layer: u32) -> Self { - self.base_array_layer(layer) - .array_layer_count(NonZeroU32::new(1)) + self.base_array_layer(layer).array_layer_count(Some(1)) } pub fn build(self) -> TextureView { @@ -759,7 +761,9 @@ pub fn data_size_bytes(desc: &wgpu::TextureDescriptor) -> usize { /// Return the size of the given texture format in bytes. pub fn format_size_bytes(format: wgpu::TextureFormat) -> u32 { - format.describe().block_size as u32 + format + .block_size(None) + .expect("Expected the format to have a block size") as u32 } /// Returns `true` if the given `wgpu::Extent3d`s are equal. diff --git a/nannou_wgpu/src/texture/reshaper/mod.rs b/nannou_wgpu/src/texture/reshaper/mod.rs index 0a2a5521b..f9269c1e8 100644 --- a/nannou_wgpu/src/texture/reshaper/mod.rs +++ b/nannou_wgpu/src/texture/reshaper/mod.rs @@ -10,11 +10,11 @@ use crate::{self as wgpu, util::DeviceExt, BufferInitDescriptor}; pub struct Reshaper { _vs_mod: wgpu::ShaderModule, _fs_mod: wgpu::ShaderModule, - bind_group_layout: wgpu::BindGroupLayout, + _bind_group_layout: wgpu::BindGroupLayout, bind_group: wgpu::BindGroup, render_pipeline: wgpu::RenderPipeline, - sampler: wgpu::Sampler, - uniform_buffer: Option, + _sampler: wgpu::Sampler, + _uniform_buffer: Option, vertex_buffer: wgpu::Buffer, } @@ -50,8 +50,8 @@ impl Reshaper { 16 => wgpu::include_wgsl!("shaders/fs_msaa16.wgsl"), _ => wgpu::include_wgsl!("shaders/fs_msaa.wgsl"), }; - let vs_mod = device.create_shader_module(&vs_desc); - let fs_mod = device.create_shader_module(&fs_desc); + let vs_mod = device.create_shader_module(vs_desc); + let fs_mod = device.create_shader_module(fs_desc); // Create the sampler for sampling from the source texture. let sampler_desc = wgpu::SamplerBuilder::new().into_descriptor(); @@ -111,11 +111,11 @@ impl Reshaper { Reshaper { _vs_mod: vs_mod, _fs_mod: fs_mod, - bind_group_layout, + _bind_group_layout: bind_group_layout, bind_group, render_pipeline, - sampler, - uniform_buffer, + _sampler: sampler, + _uniform_buffer: uniform_buffer, vertex_buffer, } } diff --git a/nannou_wgpu/src/texture/reshaper/shaders/fs.wgsl b/nannou_wgpu/src/texture/reshaper/shaders/fs.wgsl index 1b489eee6..c49bc9bec 100644 --- a/nannou_wgpu/src/texture/reshaper/shaders/fs.wgsl +++ b/nannou_wgpu/src/texture/reshaper/shaders/fs.wgsl @@ -1,15 +1,15 @@ struct FragmentOutput { - [[location(0)]] out_color: vec4; + @location(0) out_color: vec4, }; -[[group(0), binding(0)]] +@group(0) @binding(0) var tex: texture_2d; -[[group(0), binding(1)]] +@group(0) @binding(1) var tex_sampler: sampler; -[[stage(fragment)]] +@fragment fn main( - [[location(0)]] tex_coords: vec2, + @location(0) tex_coords: vec2, ) -> FragmentOutput { let out_color: vec4 = textureSample(tex, tex_sampler, tex_coords); return FragmentOutput(out_color); diff --git a/nannou_wgpu/src/texture/reshaper/shaders/fs_msaa.wgsl b/nannou_wgpu/src/texture/reshaper/shaders/fs_msaa.wgsl index 9e594eb23..0fe431c89 100644 --- a/nannou_wgpu/src/texture/reshaper/shaders/fs_msaa.wgsl +++ b/nannou_wgpu/src/texture/reshaper/shaders/fs_msaa.wgsl @@ -1,25 +1,24 @@ struct FragmentOutput { - [[location(0)]] out_color: vec4; + @location(0) out_color: vec4, }; -[[block]] struct Data { - sample_count: u32; + sample_count: u32, }; -[[group(0), binding(0)]] +@group(0) @binding(0) var tex: texture_multisampled_2d; -[[group(0), binding(1)]] +@group(0) @binding(1) var tex_sampler: sampler; -[[group(0), binding(2)]] +@group(0) @binding(2) var uniforms: Data; -[[stage(fragment)]] +@fragment fn main( - [[location(0)]] tex_coords: vec2, + @location(0) tex_coords: vec2, ) -> FragmentOutput { // Get the integer tex coordinates. - let tex_size: vec2 = textureDimensions(tex); + let tex_size: vec2 = textureDimensions(tex); let tex_x: i32 = i32(f32(tex_size.x) * tex_coords.x); let tex_y: i32 = i32(f32(tex_size.y) * tex_coords.y);; let itex_coords: vec2 = vec2(tex_x, tex_y); diff --git a/nannou_wgpu/src/texture/reshaper/shaders/fs_msaa16.wgsl b/nannou_wgpu/src/texture/reshaper/shaders/fs_msaa16.wgsl index a758d89fc..22a4df815 100644 --- a/nannou_wgpu/src/texture/reshaper/shaders/fs_msaa16.wgsl +++ b/nannou_wgpu/src/texture/reshaper/shaders/fs_msaa16.wgsl @@ -1,18 +1,18 @@ struct FragmentOutput { - [[location(0)]] out_color: vec4; + @location(0) out_color: vec4, }; -[[group(0), binding(0)]] +@group(0) @binding(0) var tex: texture_multisampled_2d; -[[group(0), binding(1)]] +@group(0) @binding(1) var tex_sampler: sampler; -[[stage(fragment)]] +@fragment fn main( - [[location(0)]] tex_coords: vec2, + @location(0) tex_coords: vec2, ) -> FragmentOutput { // Get the integer tex coordinates. - let tex_size: vec2 = textureDimensions(tex); + let tex_size: vec2 = textureDimensions(tex); let tex_x: i32 = i32(f32(tex_size.x) * tex_coords.x); let tex_y: i32 = i32(f32(tex_size.y) * tex_coords.y);; let itex_coords: vec2 = vec2(tex_x, tex_y); diff --git a/nannou_wgpu/src/texture/reshaper/shaders/fs_msaa2.wgsl b/nannou_wgpu/src/texture/reshaper/shaders/fs_msaa2.wgsl index 4f3079122..689af77b6 100644 --- a/nannou_wgpu/src/texture/reshaper/shaders/fs_msaa2.wgsl +++ b/nannou_wgpu/src/texture/reshaper/shaders/fs_msaa2.wgsl @@ -1,18 +1,18 @@ struct FragmentOutput { - [[location(0)]] out_color: vec4; + @location(0) out_color: vec4, }; -[[group(0), binding(0)]] +@group(0) @binding(0) var tex: texture_multisampled_2d; -[[group(0), binding(1)]] +@group(0) @binding(1) var tex_sampler: sampler; -[[stage(fragment)]] +@fragment fn main( - [[location(0)]] tex_coords: vec2, + @location(0) tex_coords: vec2, ) -> FragmentOutput { // Get the integer tex coordinates. - let tex_size: vec2 = textureDimensions(tex); + let tex_size: vec2 = textureDimensions(tex); let tex_x: i32 = i32(f32(tex_size.x) * tex_coords.x); let tex_y: i32 = i32(f32(tex_size.y) * tex_coords.y);; let itex_coords: vec2 = vec2(tex_x, tex_y); diff --git a/nannou_wgpu/src/texture/reshaper/shaders/fs_msaa4.wgsl b/nannou_wgpu/src/texture/reshaper/shaders/fs_msaa4.wgsl index df32af9de..96c88e341 100644 --- a/nannou_wgpu/src/texture/reshaper/shaders/fs_msaa4.wgsl +++ b/nannou_wgpu/src/texture/reshaper/shaders/fs_msaa4.wgsl @@ -1,18 +1,18 @@ struct FragmentOutput { - [[location(0)]] out_color: vec4; + @location(0) out_color: vec4, }; -[[group(0), binding(0)]] +@group(0) @binding(0) var tex: texture_multisampled_2d; -[[group(0), binding(1)]] +@group(0) @binding(1) var tex_sampler: sampler; -[[stage(fragment)]] +@fragment fn main( - [[location(0)]] tex_coords: vec2, + @location(0) tex_coords: vec2, ) -> FragmentOutput { // Get the integer tex coordinates. - let tex_size: vec2 = textureDimensions(tex); + let tex_size: vec2 = textureDimensions(tex); let tex_x: i32 = i32(f32(tex_size.x) * tex_coords.x); let tex_y: i32 = i32(f32(tex_size.y) * tex_coords.y);; let itex_coords: vec2 = vec2(tex_x, tex_y); diff --git a/nannou_wgpu/src/texture/reshaper/shaders/fs_msaa8.wgsl b/nannou_wgpu/src/texture/reshaper/shaders/fs_msaa8.wgsl index cb9a45551..5e52e2c09 100644 --- a/nannou_wgpu/src/texture/reshaper/shaders/fs_msaa8.wgsl +++ b/nannou_wgpu/src/texture/reshaper/shaders/fs_msaa8.wgsl @@ -1,18 +1,18 @@ struct FragmentOutput { - [[location(0)]] out_color: vec4; + @location(0) out_color: vec4, }; -[[group(0), binding(0)]] +@group(0) @binding(0) var tex: texture_multisampled_2d; -[[group(0), binding(1)]] +@group(0) @binding(1) var tex_sampler: sampler; -[[stage(fragment)]] +@fragment fn main( - [[location(0)]] tex_coords: vec2, + @location(0) tex_coords: vec2, ) -> FragmentOutput { // Get the integer tex coordinates. - let tex_size: vec2 = textureDimensions(tex); + let tex_size: vec2 = textureDimensions(tex); let tex_x: i32 = i32(f32(tex_size.x) * tex_coords.x); let tex_y: i32 = i32(f32(tex_size.y) * tex_coords.y);; let itex_coords: vec2 = vec2(tex_x, tex_y); diff --git a/nannou_wgpu/src/texture/reshaper/shaders/vs.wgsl b/nannou_wgpu/src/texture/reshaper/shaders/vs.wgsl index e3257e84c..7859f9c3a 100644 --- a/nannou_wgpu/src/texture/reshaper/shaders/vs.wgsl +++ b/nannou_wgpu/src/texture/reshaper/shaders/vs.wgsl @@ -1,11 +1,11 @@ struct VertexOutput { - [[location(0)]] tex_coords: vec2; - [[builtin(position)]] out_pos: vec4; + @location(0) tex_coords: vec2, + @builtin(position) out_pos: vec4, }; -[[stage(vertex)]] +@vertex fn main( - [[location(0)]] pos: vec2, + @location(0) pos: vec2, ) -> VertexOutput { let out_pos: vec4 = vec4(pos, 0.0, 1.0); let tex_coords: vec2 = vec2(pos.x * 0.5 + 0.5, 1.0 - (pos.y * 0.5 + 0.5)); diff --git a/nannou_wgpu/src/texture/row_padded_buffer.rs b/nannou_wgpu/src/texture/row_padded_buffer.rs index e76764783..2b41a4dfe 100644 --- a/nannou_wgpu/src/texture/row_padded_buffer.rs +++ b/nannou_wgpu/src/texture/row_padded_buffer.rs @@ -217,8 +217,8 @@ impl RowPaddedBuffer { // note: this is the layout of *this buffer*. layout: wgpu::ImageDataLayout { offset: 0, - bytes_per_row: std::num::NonZeroU32::new(self.padded_width()), - rows_per_image: std::num::NonZeroU32::new(self.height), + bytes_per_row: Some(self.padded_width()), + rows_per_image: Some(self.height), }, }; let texture_view = texture.as_image_copy();