From d5aa6b2e4afc6f53fc93367eef89cc5a48082392 Mon Sep 17 00:00:00 2001 From: chyyran Date: Fri, 2 Feb 2024 00:51:17 -0500 Subject: [PATCH] rt(wgpu): sketch out skeleton for filter chain logic --- librashader-runtime-wgpu/src/buffer.rs | 12 ++-- librashader-runtime-wgpu/src/filter_chain.rs | 68 +++++++++++++++++-- librashader-runtime-wgpu/src/filter_pass.rs | 6 +- librashader-runtime-wgpu/src/framebuffer.rs | 16 ++++- .../src/graphics_pipeline.rs | 2 + librashader-runtime-wgpu/src/texture.rs | 4 +- 6 files changed, 89 insertions(+), 19 deletions(-) diff --git a/librashader-runtime-wgpu/src/buffer.rs b/librashader-runtime-wgpu/src/buffer.rs index f67979f..a41352f 100644 --- a/librashader-runtime-wgpu/src/buffer.rs +++ b/librashader-runtime-wgpu/src/buffer.rs @@ -3,8 +3,7 @@ use std::sync::Arc; pub struct WgpuMappedBuffer { buffer: wgpu::Buffer, - backing: Box<[u8]>, - device: Arc + shadow: Box<[u8]>, } impl WgpuMappedBuffer { @@ -23,8 +22,7 @@ impl WgpuMappedBuffer { WgpuMappedBuffer { buffer, - backing: vec![0u8; size as usize].into_boxed_slice(), - device: Arc::clone(&device) + shadow: vec![0u8; size as usize].into_boxed_slice(), } } @@ -35,7 +33,7 @@ impl WgpuMappedBuffer { /// Write the contents of the backing buffer to the device buffer. pub fn flush(&self) { self.buffer.slice(..) - .get_mapped_range_mut().copy_from_slice(&self.backing) + .get_mapped_range_mut().copy_from_slice(&self.shadow) } } @@ -43,12 +41,12 @@ impl Deref for WgpuMappedBuffer { type Target = [u8]; fn deref(&self) -> &Self::Target { - self.backing.deref() + self.shadow.deref() } } impl DerefMut for WgpuMappedBuffer { fn deref_mut(&mut self) -> &mut Self::Target { - self.backing.deref_mut() + self.shadow.deref_mut() } } \ No newline at end of file diff --git a/librashader-runtime-wgpu/src/filter_chain.rs b/librashader-runtime-wgpu/src/filter_chain.rs index f4a07ae..9381298 100644 --- a/librashader-runtime-wgpu/src/filter_chain.rs +++ b/librashader-runtime-wgpu/src/filter_chain.rs @@ -29,6 +29,7 @@ use crate::draw_quad::DrawQuad; use crate::error; use crate::error::FilterChainError; use crate::filter_pass::FilterPass; +use crate::framebuffer::OutputImage; use crate::graphics_pipeline::WgpuGraphicsPipeline; use crate::luts::LutTexture; use crate::options::FrameOptionsWGPU; @@ -234,10 +235,10 @@ impl FilterChainWGPU { Ok(filters.into_boxed_slice()) } - pub fn frame(&mut self, + pub fn frame<'a>(&mut self, input: wgpu::Texture, - viewport: &Viewport, - cmd: wgpu::CommandEncoder, + viewport: &Viewport>, + cmd: &mut wgpu::CommandEncoder, frame_count: usize, options: Option<&FrameOptionsWGPU>, @@ -322,8 +323,67 @@ impl FilterChainWGPU { let passes_len = passes.len(); let (pass, last) = passes.split_at_mut(passes_len - 1); - // let frame_direction = options.map_or(1, |f| f.frame_direction); + let frame_direction = options.map_or(1, |f| f.frame_direction); + + for (index, pass) in pass.iter_mut().enumerate() { + let target = &self.output_framebuffers[index]; + source.filter_mode = pass.config.filter; + source.wrap_mode = pass.config.wrap_mode; + source.mip_filter = pass.config.filter; + + let output_image = OutputImage::new(target); + let out = RenderTarget::identity(&output_image); + + pass.draw( + cmd, + index, + &self.common, + pass.config.get_frame_count(frame_count), + frame_direction, + viewport, + &original, + &source, + &out, + QuadType::Offscreen + )?; + + if target.max_miplevels > 1 && !self.disable_mipmaps { + // todo: mipmaps + } + + source = self.common.output_textures[index].clone().unwrap(); + } + + // try to hint the optimizer + assert_eq!(last.len(), 1); + + if let Some(pass) = last.iter_mut().next() { + if pass.graphics_pipeline.format != viewport.output.format { + // need to recompile + pass.graphics_pipeline.recompile(viewport.output.format); + } + source.filter_mode = pass.config.filter; + source.wrap_mode = pass.config.wrap_mode; + source.mip_filter = pass.config.filter; + let output_image = &viewport.output; + let out = RenderTarget::viewport_with_output(output_image, viewport); + pass.draw( + cmd, + passes_len - 1, + &self.common, + pass.config.get_frame_count(frame_count), + frame_direction, + viewport, + &original, + &source, + &out, + QuadType::Final + )?; + } + + // self.push_history(input, cmd)?; + self.common.internal_frame_count = self.common.internal_frame_count.wrapping_add(1); Ok(()) } diff --git a/librashader-runtime-wgpu/src/filter_pass.rs b/librashader-runtime-wgpu/src/filter_pass.rs index 89cd841..151feff 100644 --- a/librashader-runtime-wgpu/src/filter_pass.rs +++ b/librashader-runtime-wgpu/src/filter_pass.rs @@ -86,7 +86,7 @@ impl FilterPass { parent: &FilterCommon, frame_count: u32, frame_direction: i32, - viewport: &Viewport, + viewport: &Viewport, original: &InputImage, source: &InputImage, output: &RenderTarget, @@ -201,7 +201,7 @@ impl FilterPass { Ok(()) } - fn build_semantics<'a, 'b>( + fn build_semantics<'a>( &mut self, pass_index: usize, parent: &FilterCommon, @@ -214,7 +214,7 @@ impl FilterPass { source: &InputImage, main_heap: &'a mut FxHashMap>, sampler_heap: &'a mut FxHashMap> - ) where 'a: 'b { + ) { Self::bind_semantics( &self.device, &parent.samplers, diff --git a/librashader-runtime-wgpu/src/framebuffer.rs b/librashader-runtime-wgpu/src/framebuffer.rs index 19b09fb..dbb4925 100644 --- a/librashader-runtime-wgpu/src/framebuffer.rs +++ b/librashader-runtime-wgpu/src/framebuffer.rs @@ -1,7 +1,19 @@ use wgpu::TextureView; use librashader_common::Size; +use crate::texture::OwnedImage; -pub(crate) struct OutputImage { +pub struct OutputImage<'a> { pub size: Size, - pub view: TextureView + pub view: &'a wgpu::TextureView, + pub format: wgpu::TextureFormat, +} + +impl<'a> OutputImage<'a> { + pub fn new(image: &'a OwnedImage) -> Self { + Self { + size: image.size, + view: &image.view, + format: image.image.format() + } + } } \ No newline at end of file diff --git a/librashader-runtime-wgpu/src/graphics_pipeline.rs b/librashader-runtime-wgpu/src/graphics_pipeline.rs index 10eb565..ec2db5d 100644 --- a/librashader-runtime-wgpu/src/graphics_pipeline.rs +++ b/librashader-runtime-wgpu/src/graphics_pipeline.rs @@ -11,6 +11,7 @@ use crate::framebuffer::OutputImage; pub struct WgpuGraphicsPipeline { pub layout: PipelineLayoutObjects, render_pipeline: wgpu::RenderPipeline, + pub format: wgpu::TextureFormat } pub struct PipelineLayoutObjects { @@ -201,6 +202,7 @@ impl WgpuGraphicsPipeline { Self { layout, render_pipeline, + format: render_pass_format } } diff --git a/librashader-runtime-wgpu/src/texture.rs b/librashader-runtime-wgpu/src/texture.rs index 0cd38e9..e950f97 100644 --- a/librashader-runtime-wgpu/src/texture.rs +++ b/librashader-runtime-wgpu/src/texture.rs @@ -13,7 +13,6 @@ pub struct OwnedImage { pub max_miplevels: u32, pub levels: u32, pub size: Size, - pub format: wgpu::TextureFormat, } pub enum Handle<'a, T> { @@ -98,7 +97,6 @@ impl OwnedImage { max_miplevels, levels: std::cmp::min(max_miplevels, size.calculate_miplevels()), size, - format, } } @@ -117,7 +115,7 @@ impl OwnedImage { if self.size != size || (mipmap && self.max_miplevels == 1) || (!mipmap && self.max_miplevels != 1) - || format != self.format + || format != self.image.format() { let mut new = OwnedImage::new(Arc::clone(&self.device), size, self.max_miplevels, format.into()); std::mem::swap(self, &mut new);