rt(wgpu): sketch out skeleton for filter chain logic

This commit is contained in:
chyyran 2024-02-02 00:51:17 -05:00 committed by Ronny Chan
parent cc26be486b
commit d5aa6b2e4a
6 changed files with 89 additions and 19 deletions

View file

@ -3,8 +3,7 @@ use std::sync::Arc;
pub struct WgpuMappedBuffer { pub struct WgpuMappedBuffer {
buffer: wgpu::Buffer, buffer: wgpu::Buffer,
backing: Box<[u8]>, shadow: Box<[u8]>,
device: Arc<wgpu::Device>
} }
impl WgpuMappedBuffer { impl WgpuMappedBuffer {
@ -23,8 +22,7 @@ impl WgpuMappedBuffer {
WgpuMappedBuffer { WgpuMappedBuffer {
buffer, buffer,
backing: vec![0u8; size as usize].into_boxed_slice(), shadow: vec![0u8; size as usize].into_boxed_slice(),
device: Arc::clone(&device)
} }
} }
@ -35,7 +33,7 @@ impl WgpuMappedBuffer {
/// Write the contents of the backing buffer to the device buffer. /// Write the contents of the backing buffer to the device buffer.
pub fn flush(&self) { pub fn flush(&self) {
self.buffer.slice(..) 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]; type Target = [u8];
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
self.backing.deref() self.shadow.deref()
} }
} }
impl DerefMut for WgpuMappedBuffer { impl DerefMut for WgpuMappedBuffer {
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
self.backing.deref_mut() self.shadow.deref_mut()
} }
} }

View file

@ -29,6 +29,7 @@ use crate::draw_quad::DrawQuad;
use crate::error; use crate::error;
use crate::error::FilterChainError; use crate::error::FilterChainError;
use crate::filter_pass::FilterPass; use crate::filter_pass::FilterPass;
use crate::framebuffer::OutputImage;
use crate::graphics_pipeline::WgpuGraphicsPipeline; use crate::graphics_pipeline::WgpuGraphicsPipeline;
use crate::luts::LutTexture; use crate::luts::LutTexture;
use crate::options::FrameOptionsWGPU; use crate::options::FrameOptionsWGPU;
@ -234,10 +235,10 @@ impl FilterChainWGPU {
Ok(filters.into_boxed_slice()) Ok(filters.into_boxed_slice())
} }
pub fn frame(&mut self, pub fn frame<'a>(&mut self,
input: wgpu::Texture, input: wgpu::Texture,
viewport: &Viewport<OwnedImage>, viewport: &Viewport<OutputImage<'a>>,
cmd: wgpu::CommandEncoder, cmd: &mut wgpu::CommandEncoder,
frame_count: usize, frame_count: usize,
options: Option<&FrameOptionsWGPU>, options: Option<&FrameOptionsWGPU>,
@ -322,8 +323,67 @@ impl FilterChainWGPU {
let passes_len = passes.len(); let passes_len = passes.len();
let (pass, last) = passes.split_at_mut(passes_len - 1); 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(()) Ok(())
} }

View file

@ -86,7 +86,7 @@ impl FilterPass {
parent: &FilterCommon, parent: &FilterCommon,
frame_count: u32, frame_count: u32,
frame_direction: i32, frame_direction: i32,
viewport: &Viewport<OwnedImage>, viewport: &Viewport<OutputImage>,
original: &InputImage, original: &InputImage,
source: &InputImage, source: &InputImage,
output: &RenderTarget<OutputImage>, output: &RenderTarget<OutputImage>,
@ -201,7 +201,7 @@ impl FilterPass {
Ok(()) Ok(())
} }
fn build_semantics<'a, 'b>( fn build_semantics<'a>(
&mut self, &mut self,
pass_index: usize, pass_index: usize,
parent: &FilterCommon, parent: &FilterCommon,
@ -214,7 +214,7 @@ impl FilterPass {
source: &InputImage, source: &InputImage,
main_heap: &'a mut FxHashMap<u32, WgpuArcBinding<wgpu::TextureView>>, main_heap: &'a mut FxHashMap<u32, WgpuArcBinding<wgpu::TextureView>>,
sampler_heap: &'a mut FxHashMap<u32, WgpuArcBinding<wgpu::Sampler>> sampler_heap: &'a mut FxHashMap<u32, WgpuArcBinding<wgpu::Sampler>>
) where 'a: 'b { ) {
Self::bind_semantics( Self::bind_semantics(
&self.device, &self.device,
&parent.samplers, &parent.samplers,

View file

@ -1,7 +1,19 @@
use wgpu::TextureView; use wgpu::TextureView;
use librashader_common::Size; use librashader_common::Size;
use crate::texture::OwnedImage;
pub(crate) struct OutputImage { pub struct OutputImage<'a> {
pub size: Size<u32>, pub size: Size<u32>,
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()
}
}
} }

View file

@ -11,6 +11,7 @@ use crate::framebuffer::OutputImage;
pub struct WgpuGraphicsPipeline { pub struct WgpuGraphicsPipeline {
pub layout: PipelineLayoutObjects, pub layout: PipelineLayoutObjects,
render_pipeline: wgpu::RenderPipeline, render_pipeline: wgpu::RenderPipeline,
pub format: wgpu::TextureFormat
} }
pub struct PipelineLayoutObjects { pub struct PipelineLayoutObjects {
@ -201,6 +202,7 @@ impl WgpuGraphicsPipeline {
Self { Self {
layout, layout,
render_pipeline, render_pipeline,
format: render_pass_format
} }
} }

View file

@ -13,7 +13,6 @@ pub struct OwnedImage {
pub max_miplevels: u32, pub max_miplevels: u32,
pub levels: u32, pub levels: u32,
pub size: Size<u32>, pub size: Size<u32>,
pub format: wgpu::TextureFormat,
} }
pub enum Handle<'a, T> { pub enum Handle<'a, T> {
@ -98,7 +97,6 @@ impl OwnedImage {
max_miplevels, max_miplevels,
levels: std::cmp::min(max_miplevels, size.calculate_miplevels()), levels: std::cmp::min(max_miplevels, size.calculate_miplevels()),
size, size,
format,
} }
} }
@ -117,7 +115,7 @@ impl OwnedImage {
if self.size != size if self.size != size
|| (mipmap && self.max_miplevels == 1) || (mipmap && self.max_miplevels == 1)
|| (!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()); let mut new = OwnedImage::new(Arc::clone(&self.device), size, self.max_miplevels, format.into());
std::mem::swap(self, &mut new); std::mem::swap(self, &mut new);