From 24428186a3f931db4813e1078c3c66faa84e9c9a Mon Sep 17 00:00:00 2001 From: jazzfool Date: Mon, 16 Dec 2024 01:59:37 +1100 Subject: [PATCH] render: scale quad by logical size, per-player uniforms --- src/pipeline.rs | 78 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 54 insertions(+), 24 deletions(-) diff --git a/src/pipeline.rs b/src/pipeline.rs index 76a0be0..b718640 100644 --- a/src/pipeline.rs +++ b/src/pipeline.rs @@ -2,8 +2,9 @@ use iced_wgpu::primitive::Primitive; use iced_wgpu::wgpu; use std::{ collections::{btree_map::Entry, BTreeMap}, + num::NonZero, sync::{ - atomic::{AtomicBool, Ordering}, + atomic::{AtomicBool, AtomicUsize, Ordering}, Arc, Mutex, }, }; @@ -11,14 +12,19 @@ use std::{ #[repr(C)] struct Uniforms { rect: [f32; 4], + // because wgpu min_uniform_buffer_offset_alignment + _pad: [u8; 240], } struct VideoEntry { texture_y: wgpu::Texture, texture_uv: wgpu::Texture, - uniforms: wgpu::Buffer, + instances: wgpu::Buffer, bg0: wgpu::BindGroup, alive: Arc, + + prepare_index: AtomicUsize, + render_index: AtomicUsize, } struct VideoPipeline { @@ -69,7 +75,7 @@ impl VideoPipeline { visibility: wgpu::ShaderStages::VERTEX, ty: wgpu::BindingType::Buffer { ty: wgpu::BufferBindingType::Uniform, - has_dynamic_offset: false, + has_dynamic_offset: true, min_binding_size: None, }, count: None, @@ -195,9 +201,9 @@ impl VideoPipeline { array_layer_count: None, }); - let buffer = device.create_buffer(&wgpu::BufferDescriptor { + let instances = device.create_buffer(&wgpu::BufferDescriptor { label: Some("iced_video_player uniform buffer"), - size: std::mem::size_of::() as _, + size: 256 * std::mem::size_of::() as u64, // max 256 video players per frame usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::UNIFORM, mapped_at_creation: false, }); @@ -221,9 +227,9 @@ impl VideoPipeline { wgpu::BindGroupEntry { binding: 3, resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding { - buffer: &buffer, + buffer: &instances, offset: 0, - size: None, + size: Some(NonZero::new(std::mem::size_of::() as _).unwrap()), }), }, ], @@ -232,9 +238,12 @@ impl VideoPipeline { entry.insert(VideoEntry { texture_y, texture_uv, - uniforms: buffer, + instances, bg0: bind_group, alive: Arc::clone(alive), + + prepare_index: AtomicUsize::new(0), + render_index: AtomicUsize::new(0), }); } @@ -295,13 +304,13 @@ impl VideoPipeline { if let Some(video) = self.videos.remove(&id) { video.texture_y.destroy(); video.texture_uv.destroy(); - video.uniforms.destroy(); + video.instances.destroy(); } } } fn prepare(&mut self, queue: &wgpu::Queue, video_id: u64, bounds: &iced::Rectangle) { - if let Some(video) = self.videos.get(&video_id) { + if let Some(video) = self.videos.get_mut(&video_id) { let uniforms = Uniforms { rect: [ bounds.x, @@ -309,13 +318,21 @@ impl VideoPipeline { bounds.x + bounds.width, bounds.y + bounds.height, ], + _pad: [0; 240], }; - queue.write_buffer(&video.uniforms, 0, unsafe { - std::slice::from_raw_parts( - &uniforms as *const _ as *const u8, - std::mem::size_of::(), - ) - }); + queue.write_buffer( + &video.instances, + (video.prepare_index.load(Ordering::Relaxed) * std::mem::size_of::()) + as u64, + unsafe { + std::slice::from_raw_parts( + &uniforms as *const _ as *const u8, + std::mem::size_of::(), + ) + }, + ); + video.prepare_index.fetch_add(1, Ordering::Relaxed); + video.render_index.store(0, Ordering::Relaxed); } self.cleanup(); @@ -325,7 +342,7 @@ impl VideoPipeline { &self, target: &wgpu::TextureView, encoder: &mut wgpu::CommandEncoder, - viewport: &iced::Rectangle, + clip: &iced::Rectangle, video_id: u64, ) { if let Some(video) = self.videos.get(&video_id) { @@ -345,14 +362,19 @@ impl VideoPipeline { }); pass.set_pipeline(&self.pipeline); - pass.set_bind_group(0, &video.bg0, &[]); - pass.set_scissor_rect( - viewport.x as _, - viewport.y as _, - viewport.width as _, - viewport.height as _, + pass.set_bind_group( + 0, + &video.bg0, + &[ + (video.render_index.load(Ordering::Relaxed) * std::mem::size_of::()) + as u32, + ], ); + pass.set_scissor_rect(clip.x as _, clip.y as _, clip.width as _, clip.height as _); pass.draw(0..6, 0..1); + + video.prepare_index.store(0, Ordering::Relaxed); + video.render_index.fetch_add(1, Ordering::Relaxed); } } } @@ -411,7 +433,15 @@ impl Primitive for VideoPrimitive { ); } - pipeline.prepare(queue, self.video_id, &(*bounds * viewport.projection())); + pipeline.prepare( + queue, + self.video_id, + &(*bounds + * iced::Transformation::orthographic( + viewport.logical_size().width as _, + viewport.logical_size().height as _, + )), + ); } fn render(