diff --git a/corcovado/src/sys/windows/tcp.rs b/corcovado/src/sys/windows/tcp.rs index 71b4d837e6..0703a0b925 100644 --- a/corcovado/src/sys/windows/tcp.rs +++ b/corcovado/src/sys/windows/tcp.rs @@ -254,12 +254,12 @@ impl TcpStream { } } - fn inner(&self) -> MutexGuard { + fn inner(&self) -> MutexGuard<'_, StreamInner> { self.imp.inner() } #[allow(unused)] - fn before_read(&self) -> io::Result> { + fn before_read(&self) -> io::Result> { let mut me = self.inner(); match me.read { @@ -425,7 +425,7 @@ impl TcpStream { } impl StreamImp { - fn inner(&self) -> MutexGuard { + fn inner(&self) -> MutexGuard<'_, StreamInner> { self.inner.inner.lock().unwrap() } @@ -803,13 +803,13 @@ impl TcpListener { self.imp.inner.socket.take_error() } - fn inner(&self) -> MutexGuard { + fn inner(&self) -> MutexGuard<'_, ListenerInner> { self.imp.inner() } } impl ListenerImp { - fn inner(&self) -> MutexGuard { + fn inner(&self) -> MutexGuard<'_, ListenerInner> { self.inner.inner.lock().unwrap() } diff --git a/corcovado/src/sys/windows/udp.rs b/corcovado/src/sys/windows/udp.rs index 183725b19c..0378abcda6 100644 --- a/corcovado/src/sys/windows/udp.rs +++ b/corcovado/src/sys/windows/udp.rs @@ -181,10 +181,7 @@ impl UdpSocket { } Ok((data.len(), addr)) } else { - Err(io::Error::new( - io::ErrorKind::Other, - "failed to parse socket address", - )) + Err(io::Error::other("failed to parse socket address")) }; me.iocp.put_buffer(data); self.imp.schedule_read_from(&mut me); @@ -303,7 +300,7 @@ impl UdpSocket { self.imp.inner.socket.take_error() } - fn inner(&self) -> MutexGuard { + fn inner(&self) -> MutexGuard<'_, Inner> { self.imp.inner() } @@ -324,7 +321,7 @@ impl UdpSocket { } impl Imp { - fn inner(&self) -> MutexGuard { + fn inner(&self) -> MutexGuard<'_, Inner> { self.inner.inner.lock().unwrap() } diff --git a/frontends/rioterm/src/context/title.rs b/frontends/rioterm/src/context/title.rs index ec557474be..cebdbf9a5d 100644 --- a/frontends/rioterm/src/context/title.rs +++ b/frontends/rioterm/src/context/title.rs @@ -49,6 +49,7 @@ impl ContextManagerTitles { } } +#[cfg_attr(not(unix), allow(unused_variables))] pub fn create_title_extra_from_context( context: &Context, ) -> Option { diff --git a/rio-window/src/platform_impl/windows/dark_mode.rs b/rio-window/src/platform_impl/windows/dark_mode.rs index fc2f64084d..c5755336da 100644 --- a/rio-window/src/platform_impl/windows/dark_mode.rs +++ b/rio-window/src/platform_impl/windows/dark_mode.rs @@ -4,6 +4,7 @@ use std::{ffi::c_void, ptr}; use crate::utils::Lazy; use windows_sys::core::PCSTR; +use windows_sys::s; use windows_sys::Win32::Foundation::{BOOL, HWND, NTSTATUS, S_OK}; use windows_sys::Win32::System::LibraryLoader::{GetProcAddress, LoadLibraryA}; use windows_sys::Win32::System::SystemInformation::OSVERSIONINFOW; @@ -146,7 +147,7 @@ fn should_apps_use_dark_mode() -> bool { return None; } - let module = LoadLibraryA("uxtheme.dll\0".as_ptr()); + let module = LoadLibraryA(s!("uxtheme.dll")); if module.is_null() { return None; diff --git a/rio-window/src/platform_impl/windows/event_loop.rs b/rio-window/src/platform_impl/windows/event_loop.rs index c830a31651..8e89e04997 100644 --- a/rio-window/src/platform_impl/windows/event_loop.rs +++ b/rio-window/src/platform_impl/windows/event_loop.rs @@ -637,7 +637,7 @@ fn dur2timeout(dur: Duration) -> u32 { .checked_mul(1000) .and_then(|ms| ms.checked_add((dur.subsec_nanos() as u64) / 1_000_000)) .and_then(|ms| { - if dur.subsec_nanos() % 1_000_000 > 0 { + if !dur.subsec_nanos().is_multiple_of(1_000_000) { ms.checked_add(1) } else { Some(ms) diff --git a/rio-window/src/platform_impl/windows/util.rs b/rio-window/src/platform_impl/windows/util.rs index 3ae1f7d865..a7dbc77186 100644 --- a/rio-window/src/platform_impl/windows/util.rs +++ b/rio-window/src/platform_impl/windows/util.rs @@ -1,3 +1,5 @@ +#![allow(non_snake_case)] + use std::ffi::{c_void, OsStr, OsString}; use std::iter::once; use std::ops::BitAnd; diff --git a/sugarloaf/src/components/filters/runtime/buffer.rs b/sugarloaf/src/components/filters/runtime/buffer.rs deleted file mode 100644 index 59997f1485..0000000000 --- a/sugarloaf/src/components/filters/runtime/buffer.rs +++ /dev/null @@ -1,54 +0,0 @@ -// This file was originally taken from https://github.com/SnowflakePowered/librashader -// SnowflakePowered/librashader is licensed under MPL-2.0 -// https://github.com/SnowflakePowered/librashader/blob/master/LICENSE.md - -use std::ops::{Deref, DerefMut}; - -pub struct WgpuStagedBuffer { - buffer: wgpu::Buffer, - shadow: Box<[u8]>, -} - -impl WgpuStagedBuffer { - pub fn new( - device: &wgpu::Device, - usage: wgpu::BufferUsages, - size: wgpu::BufferAddress, - label: wgpu::Label<'static>, - ) -> WgpuStagedBuffer { - let buffer = device.create_buffer(&wgpu::BufferDescriptor { - label, - size, - usage: usage | wgpu::BufferUsages::COPY_DST, - mapped_at_creation: false, - }); - - WgpuStagedBuffer { - buffer, - shadow: vec![0u8; size as usize].into_boxed_slice(), - } - } - - pub fn buffer(&self) -> &wgpu::Buffer { - &self.buffer - } - - /// Write the contents of the backing buffer to the device buffer. - pub fn flush(&self, queue: &wgpu::Queue) { - queue.write_buffer(&self.buffer, 0, &self.shadow); - } -} - -impl Deref for WgpuStagedBuffer { - type Target = [u8]; - - fn deref(&self) -> &Self::Target { - self.shadow.deref() - } -} - -impl DerefMut for WgpuStagedBuffer { - fn deref_mut(&mut self) -> &mut Self::Target { - self.shadow.deref_mut() - } -} diff --git a/sugarloaf/src/components/filters/runtime/draw_quad.rs b/sugarloaf/src/components/filters/runtime/draw_quad.rs deleted file mode 100644 index eca07b4e16..0000000000 --- a/sugarloaf/src/components/filters/runtime/draw_quad.rs +++ /dev/null @@ -1,75 +0,0 @@ -// This file was originally taken from https://github.com/SnowflakePowered/librashader -// SnowflakePowered/librashader is licensed under MPL-2.0 -// https://github.com/SnowflakePowered/librashader/blob/master/LICENSE.md - -use crate::concat_arrays; -use librashader_runtime::quad::{QuadType, VertexInput}; -use wgpu::util::{BufferInitDescriptor, DeviceExt}; -use wgpu::{Buffer, Device, RenderPass}; - -const OFFSCREEN_VBO_DATA: [VertexInput; 4] = [ - VertexInput { - position: [-1.0, -1.0, 0.0, 1.0], - texcoord: [0.0, 0.0], - }, - VertexInput { - position: [-1.0, 1.0, 0.0, 1.0], - texcoord: [0.0, 1.0], - }, - VertexInput { - position: [1.0, -1.0, 0.0, 1.0], - texcoord: [1.0, 0.0], - }, - VertexInput { - position: [1.0, 1.0, 0.0, 1.0], - texcoord: [1.0, 1.0], - }, -]; - -const FINAL_VBO_DATA: [VertexInput; 4] = [ - VertexInput { - position: [0.0, 0.0, 0.0, 1.0], - texcoord: [0.0, 0.0], - }, - VertexInput { - position: [0.0, 1.0, 0.0, 1.0], - texcoord: [0.0, 1.0], - }, - VertexInput { - position: [1.0, 0.0, 0.0, 1.0], - texcoord: [1.0, 0.0], - }, - VertexInput { - position: [1.0, 1.0, 0.0, 1.0], - texcoord: [1.0, 1.0], - }, -]; - -static VBO_DATA: &[VertexInput; 8] = &concat_arrays!(OFFSCREEN_VBO_DATA, FINAL_VBO_DATA); - -pub struct DrawQuad { - buffer: Buffer, -} - -impl DrawQuad { - pub fn new(device: &Device) -> DrawQuad { - let buffer = device.create_buffer_init(&BufferInitDescriptor { - label: Some("librashader vbo"), - contents: bytemuck::cast_slice(VBO_DATA), - usage: wgpu::BufferUsages::VERTEX, - }); - - DrawQuad { buffer } - } - - pub fn draw_quad<'a, 'b: 'a>(&'b self, cmd: &mut RenderPass<'a>, vbo: QuadType) { - cmd.set_vertex_buffer(0, self.buffer.slice(0..)); - - let offset = match vbo { - QuadType::Offscreen => 0..4, - QuadType::Final => 4..8, - }; - - cmd.draw(offset, 0..1) - } -} diff --git a/sugarloaf/src/components/filters/runtime/error.rs b/sugarloaf/src/components/filters/runtime/error.rs deleted file mode 100644 index 974472bc19..0000000000 --- a/sugarloaf/src/components/filters/runtime/error.rs +++ /dev/null @@ -1,43 +0,0 @@ -// This file was originally taken from https://github.com/SnowflakePowered/librashader -// SnowflakePowered/librashader is licensed under MPL-2.0 -// https://github.com/SnowflakePowered/librashader/blob/master/LICENSE.md - -//! wgpu shader runtime errors. -use librashader_preprocess::PreprocessError; -use librashader_presets::ParsePresetError; -use librashader_reflect::error::{ShaderCompileError, ShaderReflectError}; -use librashader_runtime::image::ImageError; -use thiserror::Error; - -/// Cumulative error type for wgpu filter chains. -#[derive(Error, Debug)] -#[non_exhaustive] -pub enum FilterChainError { - #[error("shader preset parse error")] - ShaderPresetError(#[from] ParsePresetError), - #[error("shader preprocess error")] - ShaderPreprocessError(#[from] PreprocessError), - #[error("shader compile error")] - ShaderCompileError(#[source] Box), - #[error("shader reflect error")] - ShaderReflectError(#[source] Box), - #[error("lut loading error")] - LutLoadError(#[from] ImageError), - #[error("unreachable")] - Infallible(#[from] std::convert::Infallible), -} - -/// Result type for wgpu filter chains. -pub type Result = std::result::Result; - -impl From for FilterChainError { - fn from(error: ShaderCompileError) -> Self { - FilterChainError::ShaderCompileError(Box::new(error)) - } -} - -impl From for FilterChainError { - fn from(error: ShaderReflectError) -> Self { - FilterChainError::ShaderReflectError(Box::new(error)) - } -} diff --git a/sugarloaf/src/components/filters/runtime/filter_chain.rs b/sugarloaf/src/components/filters/runtime/filter_chain.rs deleted file mode 100644 index 8b2b8d1c35..0000000000 --- a/sugarloaf/src/components/filters/runtime/filter_chain.rs +++ /dev/null @@ -1,613 +0,0 @@ -// This file was originally taken from https://github.com/SnowflakePowered/librashader -// The file has changed to avoid use atomic reference counter of wgpu Device and Queue structs -// SnowflakePowered/librashader is licensed under MPL-2.0 -// https://github.com/SnowflakePowered/librashader/blob/master/LICENSE.md - -use crate::context::webgpu::WgpuContext; -use librashader_common::map::FastHashMap; -use librashader_presets::ShaderFeatures; -use librashader_presets::ShaderPreset; -use librashader_reflect::back::targets::WGSL; -use librashader_reflect::back::{CompileReflectShader, CompileShader}; -use librashader_reflect::front::SpirvCompilation; -use librashader_reflect::reflect::presets::{CompilePresetTarget, ShaderPassArtifact}; -use librashader_reflect::reflect::semantics::ShaderSemantics; -use librashader_reflect::reflect::ReflectShader; -use librashader_runtime::binding::BindingUtil; -use librashader_runtime::image::{ImageError, LoadedTexture, UVDirection}; -use librashader_runtime::quad::QuadType; -use librashader_runtime::uniforms::UniformStorage; -#[cfg(not(target_arch = "wasm32"))] -use rayon::prelude::*; -use std::collections::VecDeque; -use std::path::Path; - -use rayon::ThreadPoolBuilder; -use std::sync::Arc; - -use crate::components::filters::runtime::buffer::WgpuStagedBuffer; -use crate::components::filters::runtime::draw_quad::DrawQuad; -use librashader_common::{FilterMode, Size, Viewport, WrapMode}; -use librashader_reflect::reflect::naga::{Naga, NagaLoweringOptions}; -use librashader_runtime::framebuffer::FramebufferInit; -use librashader_runtime::render_target::RenderTarget; -use librashader_runtime::scaling::ScaleFramebuffer; -use wgpu::{Device, TextureFormat}; - -use crate::components::filters::runtime::error::FilterChainError; -use crate::components::filters::runtime::filter_pass::FilterPass; -use crate::components::filters::runtime::framebuffer::WgpuOutputView; -use crate::components::filters::runtime::graphics_pipeline::WgpuGraphicsPipeline; -use crate::components::filters::runtime::luts::LutTexture; -use crate::components::filters::runtime::mipmap::MipmapGen; -use crate::components::filters::runtime::options::{ - FilterChainOptionsWgpu, FrameOptionsWgpu, -}; -use crate::components::filters::runtime::samplers::SamplerSet; -use crate::components::filters::runtime::texture::{InputImage, OwnedImage}; -use crate::components::filters::runtime::{error, format_from_image_to_texture}; - -mod compile { - use super::*; - use librashader_pack::{PassResource, TextureResource}; - - pub type ShaderPassMeta = ShaderPassArtifact< - Box + Send>, - >; - - pub fn compile_passes( - shaders: Vec, - textures: &[TextureResource], - ) -> Result<(Vec, ShaderSemantics), Box> { - let (passes, semantics) = WGSL::compile_preset_passes::< - SpirvCompilation, - Naga, - FilterChainError, - >(shaders, textures.iter().map(|t| &t.meta))?; - Ok((passes, semantics)) - } -} - -use compile::{compile_passes, ShaderPassMeta}; -use librashader_pack::{ShaderPresetPack, TextureResource}; -use librashader_runtime::parameters::RuntimeParameters; - -/// A wgpu filter chain. -pub struct FilterChain { - pub(crate) common: FilterCommon, - passes: Box<[FilterPass]>, - output_framebuffers: Box<[OwnedImage]>, - feedback_framebuffers: Box<[OwnedImage]>, - history_framebuffers: VecDeque, - disable_mipmaps: bool, - mipmapper: MipmapGen, - default_frame_options: FrameOptionsWgpu, - draw_last_pass_feedback: bool, -} - -pub(crate) struct FilterCommon { - pub output_textures: Box<[Option]>, - pub feedback_textures: Box<[Option]>, - pub history_textures: Box<[Option]>, - pub luts: FastHashMap, - pub samplers: SamplerSet, - pub config: RuntimeParameters, - pub(crate) draw_quad: DrawQuad, -} - -impl FilterChain { - /// Load the shader preset at the given path into a filter chain. - pub fn load_from_path( - path: impl AsRef, - features: ShaderFeatures, - device: &Device, - queue: &wgpu::Queue, - options: Option<&FilterChainOptionsWgpu>, - ) -> Result> { - // load passes from preset - let preset = match ShaderPreset::try_parse(path, features) { - Ok(preset) => preset, - Err(error) => { - return Err(Box::new(FilterChainError::ShaderPresetError(error))) - } - }; - - Self::load_from_preset(preset, device, queue, options) - } - - /// Load a filter chain from a pre-parsed `ShaderPreset`. - pub fn load_from_preset( - preset: ShaderPreset, - device: &Device, - queue: &wgpu::Queue, - options: Option<&FilterChainOptionsWgpu>, - ) -> Result> { - let preset = ShaderPresetPack::load_from_preset::(preset)?; - Self::load_from_pack(preset, device, queue, options) - } - - /// Load a filter chain from a pre-parsed and loaded `ShaderPresetPack`. - pub fn load_from_pack( - preset: ShaderPresetPack, - device: &Device, - queue: &wgpu::Queue, - options: Option<&FilterChainOptionsWgpu>, - ) -> Result> { - let mut cmd = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { - label: Some("librashader load cmd"), - }); - let filter_chain = - Self::load_from_pack_deferred(preset, device, queue, &mut cmd, options)?; - - let cmd = cmd.finish(); - - // Wait for device - let index = queue.submit([cmd]); - let _ = device.poll(wgpu::PollType::Wait { - submission_index: Some(index), - timeout: None, - }); - - Ok(filter_chain) - } - - /// Load a filter chain from a pre-parsed `ShaderPreset`, deferring and GPU-side initialization - /// to the caller. This function therefore requires no external synchronization of the device queue. - /// - /// ## Safety - /// The provided command buffer must be ready for recording and contain no prior commands. - /// The caller is responsible for ending the command buffer and immediately submitting it to a - /// graphics queue. The command buffer must be completely executed before calling [`frame`](Self::frame). - #[allow(unused)] - pub fn load_from_preset_deferred( - preset: ShaderPreset, - device: &Device, - queue: &wgpu::Queue, - cmd: &mut wgpu::CommandEncoder, - options: Option<&FilterChainOptionsWgpu>, - ) -> Result> { - let preset = ShaderPresetPack::load_from_preset::(preset)?; - Self::load_from_pack_deferred(preset, device, queue, cmd, options) - } - - /// Load a filter chain from a pre-parsed `ShaderPreset`, deferring and GPU-side initialization - /// to the caller. This function therefore requires no external synchronization of the device queue. - /// - /// ## Safety - /// The provided command buffer must be ready for recording and contain no prior commands. - /// The caller is responsible for ending the command buffer and immediately submitting it to a - /// graphics queue. The command buffer must be completely executed before calling [`frame`](Self::frame). - pub fn load_from_pack_deferred( - preset: ShaderPresetPack, - device: &Device, - queue: &wgpu::Queue, - cmd: &mut wgpu::CommandEncoder, - options: Option<&FilterChainOptionsWgpu>, - ) -> Result> { - // Create runtime parameters before preset is partially moved - let runtime_params = RuntimeParameters::new(&preset); - - let (passes, semantics) = match compile_passes(preset.passes, &preset.textures) { - Ok((passes, semantics)) => (passes, semantics), - Err(error) => return Err(error), - }; - - // cache is opt-in for wgpu, not opt-out because of feature requirements. - let disable_cache = options.is_none_or(|o| !o.enable_cache); - - // initialize passes - let filters = Self::init_passes( - device, - passes, - &semantics, - options.and_then(|o| o.adapter_info.as_ref()), - disable_cache, - )?; - - let samplers = SamplerSet::new(device); - let mut mipmapper = MipmapGen::new(device); - - let luts = FilterChain::load_luts( - device, - queue, - cmd, - &mut mipmapper, - &samplers, - preset.textures, - )?; - // - let framebuffer_gen = || { - Ok::<_, error::FilterChainError>(OwnedImage::new( - device, - Size::new(1, 1), - 1, - TextureFormat::Bgra8Unorm, - )) - }; - let input_gen = || None; - let framebuffer_init = FramebufferInit::new( - filters.iter().map(|f| &f.reflection.meta), - &framebuffer_gen, - &input_gen, - ); - - // - // // initialize output framebuffers - let (output_framebuffers, output_textures) = - framebuffer_init.init_output_framebuffers()?; - // - // initialize feedback framebuffers - let (feedback_framebuffers, feedback_textures) = - framebuffer_init.init_output_framebuffers()?; - // - // initialize history - let (history_framebuffers, history_textures) = framebuffer_init.init_history()?; - - let draw_quad = DrawQuad::new(device); - - Ok(FilterChain { - draw_last_pass_feedback: framebuffer_init.uses_final_pass_as_feedback(), - common: FilterCommon { - luts, - samplers, - config: runtime_params, - draw_quad, - output_textures, - feedback_textures, - history_textures, - }, - passes: filters, - output_framebuffers, - feedback_framebuffers, - history_framebuffers, - disable_mipmaps: options.map(|f| f.force_no_mipmaps).unwrap_or(false), - mipmapper, - default_frame_options: Default::default(), - }) - } - - fn load_luts( - device: &wgpu::Device, - queue: &wgpu::Queue, - cmd: &mut wgpu::CommandEncoder, - mipmapper: &mut MipmapGen, - sampler_set: &SamplerSet, - textures: Vec, - ) -> error::Result> { - let mut luts = FastHashMap::default(); - - #[cfg(not(target_arch = "wasm32"))] - let images_iter = textures.into_par_iter(); - - #[cfg(target_arch = "wasm32")] - let images_iter = textures.into_iter(); - - let textures = images_iter - .map(|texture| LoadedTexture::from_texture(texture, UVDirection::TopLeft)) - .collect::, ImageError>>()?; - for (index, LoadedTexture { meta, image }) in textures.into_iter().enumerate() { - let texture = - LutTexture::new(device, queue, cmd, image, &meta, mipmapper, sampler_set); - luts.insert(index, texture); - } - Ok(luts) - } - - fn push_history( - &mut self, - input: &wgpu::Texture, - cmd: &mut wgpu::CommandEncoder, - context: &crate::context::webgpu::WgpuContext, - ) { - if let Some(mut back) = self.history_framebuffers.pop_back() { - if back.image.size() != input.size() || input.format() != back.image.format() - { - // old back will get dropped.. do we need to defer? - let size = input.size(); - let _old_back = std::mem::replace( - &mut back, - OwnedImage::new( - &context.device, - Size { - width: size.width, - height: size.height, - }, - 1, - input.format(), - ), - ); - } - - back.copy_from(cmd, input, &context.device); - - self.history_framebuffers.push_front(back) - } - } - - fn init_passes( - device: &Device, - passes: Vec, - semantics: &ShaderSemantics, - adapter_info: Option<&wgpu::AdapterInfo>, - disable_cache: bool, - ) -> Result, Box> { - #[cfg(not(target_arch = "wasm32"))] - let filter_creation_fn = || { - let passes_iter = passes.into_par_iter(); - #[cfg(target_arch = "wasm32")] - let passes_iter = passes.into_iter(); - - let filters: Vec> = passes_iter - .enumerate() - .map(|(index, (config, mut reflect))| { - let reflection = reflect.reflect(index, semantics)?; - let wgsl = reflect.compile(NagaLoweringOptions { - write_pcb_as_ubo: true, - sampler_bind_group: 1, - })?; - - let ubo_size = - reflection.ubo.as_ref().map_or(0, |ubo| ubo.size as usize); - let push_size = reflection - .push_constant - .as_ref() - .map_or(0, |push| push.size as wgpu::BufferAddress); - - let uniform_storage = UniformStorage::new_with_storage( - WgpuStagedBuffer::new( - device, - wgpu::BufferUsages::UNIFORM, - ubo_size as wgpu::BufferAddress, - Some("ubo"), - ), - WgpuStagedBuffer::new( - device, - wgpu::BufferUsages::UNIFORM, - push_size as wgpu::BufferAddress, - Some("push"), - ), - ); - - let uniform_bindings = - reflection.meta.create_binding_map(|param| param.offset()); - - let render_pass_format: Option = - if let Some(format) = config.meta.get_format_override() { - format_from_image_to_texture(&format) - } else { - format_from_image_to_texture(&config.data.format) - }; - - let graphics_pipeline = WgpuGraphicsPipeline::new( - device, - &wgsl, - &reflection, - render_pass_format.unwrap_or(TextureFormat::Rgba8Unorm), - adapter_info, - disable_cache, - ); - - Ok(FilterPass { - reflection, - uniform_storage, - uniform_bindings, - source: config.data, - meta: config.meta, - graphics_pipeline, - }) - }) - .collect(); - filters - }; - - #[cfg(target_arch = "wasm32")] - let filters = filter_creation_fn(); - - #[cfg(not(target_arch = "wasm32"))] - let filters = if let Ok(thread_pool) = ThreadPoolBuilder::new() - // naga compilations can possibly use degenerate stack sizes. - .stack_size(10 * 1048576) - .build() - { - thread_pool.install(filter_creation_fn) - } else { - filter_creation_fn() - }; - - let filters: error::Result> = filters.into_iter().collect(); - let filters = filters?; - Ok(filters.into_boxed_slice()) - } - - /// Records shader rendering commands to the provided command encoder. - pub fn frame( - &mut self, - input: Arc, - viewport: &Viewport>, - cmd: &mut wgpu::CommandEncoder, - frame_count: usize, - options: Option<&FrameOptionsWgpu>, - context: &WgpuContext, - ) -> error::Result<()> { - let max = std::cmp::min(self.passes.len(), self.common.config.passes_enabled()); - let passes = &mut self.passes[0..max]; - - if let Some(options) = &options { - if options.clear_history { - for history in &mut self.history_framebuffers { - history.clear(cmd); - } - } - } - - if passes.is_empty() { - return Ok(()); - } - - let original_image_view = - input.create_view(&wgpu::TextureViewDescriptor::default()); - - let filter = passes[0].meta.filter; - let wrap_mode = passes[0].meta.wrap_mode; - - // update history - for (texture, image) in self - .common - .history_textures - .iter_mut() - .zip(self.history_framebuffers.iter()) - { - *texture = Some(image.as_input(filter, wrap_mode)); - } - - let original = InputImage { - image: Arc::clone(&input), - view: Arc::new(original_image_view), - wrap_mode, - filter_mode: filter, - mip_filter: filter, - }; - - let mut source = original.clone(); - - // swap output and feedback **before** recording command buffers - std::mem::swap( - &mut self.output_framebuffers, - &mut self.feedback_framebuffers, - ); - - let source_size = source.image.size(); - let source_size = Size { - width: source_size.width, - height: source_size.height, - }; - - let original_size = original.image.size(); - let original_size = Size { - width: original_size.width, - height: original_size.height, - }; - - // rescale render buffers to ensure all bindings are valid. - OwnedImage::scale_framebuffers_with_context( - source_size, - viewport.output.size, - original_size, - &mut self.output_framebuffers, - &mut self.feedback_framebuffers, - passes, - &context.device, - Some(&mut |index: usize, - pass: &FilterPass, - output: &OwnedImage, - feedback: &OwnedImage| { - // refresh inputs - self.common.feedback_textures[index] = - Some(feedback.as_input(pass.meta.filter, pass.meta.wrap_mode)); - self.common.output_textures[index] = - Some(output.as_input(pass.meta.filter, pass.meta.wrap_mode)); - Ok(()) - }), - )?; - - let passes_len = passes.len(); - let (pass, last) = passes.split_at_mut(passes_len - 1); - - let options = options.unwrap_or(&self.default_frame_options); - - for (index, pass) in pass.iter_mut().enumerate() { - source.filter_mode = pass.meta.filter; - source.wrap_mode = pass.meta.wrap_mode; - source.mip_filter = pass.meta.filter; - - let target = &self.output_framebuffers[index]; - let output_image = WgpuOutputView::from(target); - let out = RenderTarget::identity(&output_image)?; - - pass.draw( - cmd, - index, - &self.common, - pass.meta.get_frame_count(frame_count), - options, - viewport, - &original, - &source, - &out, - QuadType::Offscreen, - context, - )?; - - if target.max_miplevels > 1 && !self.disable_mipmaps { - let sampler = self.common.samplers.get( - WrapMode::ClampToEdge, - FilterMode::Linear, - FilterMode::Nearest, - ); - - target.generate_mipmaps( - &context.device, - cmd, - &mut self.mipmapper, - &sampler, - ); - } - - 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() { - let index = passes_len - 1; - if !pass.graphics_pipeline.has_format(viewport.output.format) { - // need to recompile - pass.graphics_pipeline - .recompile(&context.device, viewport.output.format); - } - - source.filter_mode = pass.meta.filter; - source.wrap_mode = pass.meta.wrap_mode; - source.mip_filter = pass.meta.filter; - - if self.draw_last_pass_feedback { - let target = &self.output_framebuffers[index]; - let output_image = WgpuOutputView::from(target); - let out = RenderTarget::viewport_with_output(&output_image, viewport); - - pass.draw( - cmd, - index, - &self.common, - pass.meta.get_frame_count(frame_count), - options, - viewport, - &original, - &source, - &out, - QuadType::Final, - context, - )?; - } - - let out = RenderTarget::viewport(viewport); - pass.draw( - cmd, - index, - &self.common, - pass.meta.get_frame_count(frame_count), - options, - viewport, - &original, - &source, - &out, - QuadType::Final, - context, - )?; - } - - self.push_history(&input, cmd, context); - Ok(()) - } -} diff --git a/sugarloaf/src/components/filters/runtime/filter_pass.rs b/sugarloaf/src/components/filters/runtime/filter_pass.rs deleted file mode 100644 index 84430cb504..0000000000 --- a/sugarloaf/src/components/filters/runtime/filter_pass.rs +++ /dev/null @@ -1,262 +0,0 @@ -// This file was originally taken from https://github.com/SnowflakePowered/librashader -// The file has changed to avoid use atomic reference counter of wgpu Device and Queue structs -// SnowflakePowered/librashader is licensed under MPL-2.0 -// https://github.com/SnowflakePowered/librashader/blob/master/LICENSE.md - -use crate::components::filters::runtime::buffer::WgpuStagedBuffer; -use crate::components::filters::runtime::error; -use crate::components::filters::runtime::filter_chain::FilterCommon; -use crate::components::filters::runtime::framebuffer::WgpuOutputView; -use crate::components::filters::runtime::graphics_pipeline::WgpuGraphicsPipeline; -use crate::components::filters::runtime::options::FrameOptionsWgpu; -use crate::components::filters::runtime::samplers::SamplerSet; -use crate::components::filters::runtime::texture::InputImage; -use crate::context::webgpu::WgpuContext; -use librashader_common::map::FastHashMap; -use librashader_common::{ImageFormat, Size, Viewport}; -use librashader_preprocess::ShaderSource; -use librashader_presets::PassMeta; -use librashader_reflect::reflect::semantics::{ - MemberOffset, TextureBinding, UniformBinding, -}; -use librashader_reflect::reflect::ShaderReflection; -use librashader_runtime::binding::{BindSemantics, TextureInput, UniformInputs}; -use librashader_runtime::filter_pass::FilterPassMeta; -use librashader_runtime::quad::QuadType; -use librashader_runtime::render_target::RenderTarget; -use librashader_runtime::uniforms::{NoUniformBinder, UniformStorage}; -use std::sync::Arc; -use wgpu::{BindGroupDescriptor, BindGroupEntry, BindingResource, BufferBinding}; - -pub struct FilterPass { - pub reflection: ShaderReflection, - pub(crate) uniform_storage: UniformStorage< - NoUniformBinder, - Option<()>, - WgpuStagedBuffer, - WgpuStagedBuffer, - wgpu::Device, - >, - pub uniform_bindings: FastHashMap, - pub source: ShaderSource, - pub meta: PassMeta, - pub graphics_pipeline: WgpuGraphicsPipeline, -} - -impl TextureInput for InputImage { - fn size(&self) -> Size { - let size = self.image.size(); - Size { - width: size.width, - height: size.height, - } - } -} - -pub struct WgpuArcBinding { - binding: u32, - resource: Arc, -} - -impl BindSemantics, WgpuStagedBuffer, WgpuStagedBuffer> - for FilterPass -{ - type InputTexture = InputImage; - type SamplerSet = SamplerSet; - type DescriptorSet<'a> = ( - &'a mut FastHashMap>, - &'a mut FastHashMap>, - ); - type DeviceContext = wgpu::Device; - type UniformOffset = MemberOffset; - - #[inline(always)] - fn bind_texture( - descriptors: &mut Self::DescriptorSet<'_>, - samplers: &Self::SamplerSet, - binding: &TextureBinding, - texture: &Self::InputTexture, - _device: &Self::DeviceContext, - ) { - let sampler = - samplers.get(texture.wrap_mode, texture.filter_mode, texture.mip_filter); - - let (texture_binding, sampler_binding) = descriptors; - texture_binding.insert( - binding.binding, - WgpuArcBinding { - binding: binding.binding, - resource: Arc::clone(&texture.view), - }, - ); - - sampler_binding.insert( - binding.binding, - WgpuArcBinding { - binding: binding.binding, - resource: sampler, - }, - ); - } -} - -impl FilterPass { - #[allow(clippy::too_many_arguments)] - pub(crate) fn draw( - &mut self, - cmd: &mut wgpu::CommandEncoder, - pass_index: usize, - parent: &FilterCommon, - frame_count: u32, - options: &FrameOptionsWgpu, - viewport: &Viewport, - original: &InputImage, - source: &InputImage, - output: &RenderTarget, - vbo_type: QuadType, - context: &WgpuContext, - ) -> error::Result<()> { - let mut main_heap = FastHashMap::default(); - let mut sampler_heap = FastHashMap::default(); - - self.build_semantics( - pass_index, - parent, - output.mvp, - frame_count, - options, - output.output.size, - viewport.output.size, - original, - source, - &mut main_heap, - &mut sampler_heap, - context, - ); - - let mut main_heap_array = Vec::with_capacity(main_heap.len() + 1); - let mut sampler_heap_array = Vec::with_capacity(sampler_heap.len() + 1); - - for binding in main_heap.values() { - main_heap_array.push(BindGroupEntry { - binding: binding.binding, - resource: BindingResource::TextureView(&binding.resource), - }) - } - - for binding in sampler_heap.values() { - sampler_heap_array.push(BindGroupEntry { - binding: binding.binding, - resource: BindingResource::Sampler(&binding.resource), - }) - } - - if let Some(ubo) = &self.reflection.ubo { - main_heap_array.push(BindGroupEntry { - binding: ubo.binding, - resource: BindingResource::Buffer(BufferBinding { - buffer: self.uniform_storage.inner_ubo().buffer(), - offset: 0, - size: None, - }), - }); - } - - if let Some(pcb) = &self.reflection.push_constant { - if let Some(binding) = pcb.binding { - main_heap_array.push(BindGroupEntry { - binding, - resource: BindingResource::Buffer(BufferBinding { - buffer: self.uniform_storage.inner_push().buffer(), - offset: 0, - size: None, - }), - }); - } - } - - let main_bind_group = context.device.create_bind_group(&BindGroupDescriptor { - label: Some("main bind group"), - layout: &self.graphics_pipeline.layout.main_bind_group_layout, - entries: &main_heap_array, - }); - - let sampler_bind_group = context.device.create_bind_group(&BindGroupDescriptor { - label: Some("sampler bind group"), - layout: &self.graphics_pipeline.layout.sampler_bind_group_layout, - entries: &sampler_heap_array, - }); - - let mut render_pass = self.graphics_pipeline.begin_rendering(output, cmd); - - render_pass.set_bind_group(0, &main_bind_group, &[]); - render_pass.set_bind_group(1, &sampler_bind_group, &[]); - - parent.draw_quad.draw_quad(&mut render_pass, vbo_type); - - Ok(()) - } - - #[allow(clippy::too_many_arguments)] - fn build_semantics<'a>( - &mut self, - pass_index: usize, - parent: &FilterCommon, - mvp: &[f32; 16], - frame_count: u32, - options: &FrameOptionsWgpu, - fb_size: Size, - viewport_size: Size, - original: &InputImage, - source: &InputImage, - main_heap: &'a mut FastHashMap>, - sampler_heap: &'a mut FastHashMap>, - context: &WgpuContext, - ) { - Self::bind_semantics( - &context.device, - &parent.samplers, - &mut self.uniform_storage, - &mut (main_heap, sampler_heap), - UniformInputs { - mvp, - frame_count, - rotation: options.rotation, - total_subframes: options.total_subframes, - current_subframe: options.current_subframe, - frame_direction: options.frame_direction, - framebuffer_size: fb_size, - aspect_ratio: options.aspect_ratio, - frames_per_second: options.frames_per_second, - frametime_delta: options.frametime_delta, - viewport_size, - }, - original, - source, - &self.uniform_bindings, - &self.reflection.meta.texture_meta, - parent.output_textures[0..pass_index] - .iter() - .map(|o| o.as_ref()), - parent.feedback_textures.iter().map(|o| o.as_ref()), - parent.history_textures.iter().map(|o| o.as_ref()), - parent.luts.iter().map(|(u, i)| (*u, i.as_ref())), - &self.source.parameters, - &parent.config, - ); - - // flush to buffers - self.uniform_storage.inner_ubo().flush(&context.queue); - self.uniform_storage.inner_push().flush(&context.queue); - } -} - -impl FilterPassMeta for FilterPass { - fn framebuffer_format(&self) -> ImageFormat { - self.source.format - } - - fn meta(&self) -> &PassMeta { - &self.meta - } -} diff --git a/sugarloaf/src/components/filters/runtime/framebuffer.rs b/sugarloaf/src/components/filters/runtime/framebuffer.rs deleted file mode 100644 index 4cc71afe31..0000000000 --- a/sugarloaf/src/components/filters/runtime/framebuffer.rs +++ /dev/null @@ -1,55 +0,0 @@ -// This file was originally taken from https://github.com/SnowflakePowered/librashader -// SnowflakePowered/librashader is licensed under MPL-2.0 -// https://github.com/SnowflakePowered/librashader/blob/master/LICENSE.md - -use crate::components::filters::runtime::handle::Handle; -use crate::components::filters::runtime::texture::OwnedImage; -use librashader_common::Size; -use wgpu::TextureViewDescriptor; - -/// A wgpu `TextureView` with size and texture information to output. -pub struct WgpuOutputView<'a> { - pub(crate) size: Size, - pub(crate) view: Handle<'a, wgpu::TextureView>, - pub(crate) format: wgpu::TextureFormat, -} - -impl<'a> WgpuOutputView<'a> { - /// Create an output view from an existing texture view, size, and format. - pub fn new_from_raw( - view: &'a wgpu::TextureView, - size: Size, - format: wgpu::TextureFormat, - ) -> Self { - Self { - size, - view: Handle::Borrowed(view), - format, - } - } -} - -#[doc(hidden)] -impl<'a> From<&'a OwnedImage> for WgpuOutputView<'a> { - fn from(image: &'a OwnedImage) -> Self { - Self { - size: image.size, - view: Handle::Borrowed(&image.view), - format: image.image.format(), - } - } -} - -impl From<&wgpu::Texture> for WgpuOutputView<'static> { - fn from(image: &wgpu::Texture) -> Self { - let image_size = image.size(); - Self { - size: Size { - width: image_size.width, - height: image_size.height, - }, - view: Handle::Owned(image.create_view(&TextureViewDescriptor::default())), - format: image.format(), - } - } -} diff --git a/sugarloaf/src/components/filters/runtime/graphics_pipeline.rs b/sugarloaf/src/components/filters/runtime/graphics_pipeline.rs deleted file mode 100644 index 4405a24443..0000000000 --- a/sugarloaf/src/components/filters/runtime/graphics_pipeline.rs +++ /dev/null @@ -1,331 +0,0 @@ -// This file was originally taken from https://github.com/SnowflakePowered/librashader -// The file has changed to avoid use atomic reference counter of wgpu Device and Queue structs -// SnowflakePowered/librashader is licensed under MPL-2.0 -// https://github.com/SnowflakePowered/librashader/blob/master/LICENSE.md - -use crate::components::filters::runtime::util; -use crate::components::filters::runtime::WgpuOutputView; -use librashader_cache::cache_pipeline; -use librashader_common::map::FastHashMap; -use librashader_reflect::back::wgsl::NagaWgslContext; -use librashader_reflect::back::ShaderCompilerOutput; -use librashader_reflect::reflect::ShaderReflection; -use librashader_runtime::quad::VertexInput; -use librashader_runtime::render_target::RenderTarget; -use std::borrow::Cow; -use std::convert::Infallible; -use wgpu::{ - BindGroupLayout, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingType, - BufferBindingType, BufferSize, CommandEncoder, Operations, PipelineLayout, - RenderPass, RenderPassColorAttachment, RenderPassDescriptor, SamplerBindingType, - ShaderModule, ShaderSource, ShaderStages, TextureFormat, TextureSampleType, - TextureViewDimension, VertexBufferLayout, -}; - -pub struct WgpuGraphicsPipeline { - pub layout: PipelineLayoutObjects, - cache: Option, - render_pipelines: FastHashMap, -} - -pub struct PipelineLayoutObjects { - layout: PipelineLayout, - pub main_bind_group_layout: BindGroupLayout, - pub sampler_bind_group_layout: BindGroupLayout, - fragment_entry_name: String, - vertex_entry_name: String, - vertex: ShaderModule, - fragment: ShaderModule, -} - -impl PipelineLayoutObjects { - pub fn new( - reflection: &ShaderReflection, - shader_assembly: &ShaderCompilerOutput, - device: &wgpu::Device, - ) -> Self { - let vertex = device.create_shader_module(wgpu::ShaderModuleDescriptor { - label: Some("vertex"), - source: ShaderSource::Wgsl(Cow::from(&shader_assembly.vertex)), - }); - - let fragment = device.create_shader_module(wgpu::ShaderModuleDescriptor { - label: Some("fragment"), - source: ShaderSource::Wgsl(Cow::from(&shader_assembly.fragment)), - }); - - let mut main_bindings = Vec::new(); - let mut sampler_bindings = Vec::new(); - - if let Some(push_meta) = reflection - .push_constant - .as_ref() - .filter(|push_meta| !push_meta.stage_mask.is_empty()) - { - let push_mask = util::binding_stage_to_wgpu_stage(push_meta.stage_mask); - let binding = push_meta.binding.unwrap_or(0); - main_bindings.push(BindGroupLayoutEntry { - binding, - visibility: push_mask, - ty: BindingType::Buffer { - ty: BufferBindingType::Uniform, - has_dynamic_offset: false, - min_binding_size: BufferSize::new(push_meta.size as u64), - }, - count: None, - }); - } - - if let Some(ubo_meta) = reflection - .ubo - .as_ref() - .filter(|ubo_meta| !ubo_meta.stage_mask.is_empty()) - { - let ubo_mask = util::binding_stage_to_wgpu_stage(ubo_meta.stage_mask); - main_bindings.push(BindGroupLayoutEntry { - binding: ubo_meta.binding, - visibility: ubo_mask, - ty: BindingType::Buffer { - ty: BufferBindingType::Uniform, - has_dynamic_offset: false, - min_binding_size: BufferSize::new(ubo_meta.size as u64), - }, - count: None, - }); - } - - for texture in reflection.meta.texture_meta.values() { - main_bindings.push(BindGroupLayoutEntry { - binding: texture.binding, - visibility: ShaderStages::FRAGMENT, - ty: BindingType::Texture { - sample_type: TextureSampleType::Float { filterable: true }, - view_dimension: TextureViewDimension::D2, - multisampled: false, - }, - count: None, - }); - - sampler_bindings.push(BindGroupLayoutEntry { - binding: texture.binding, - visibility: ShaderStages::FRAGMENT, - ty: BindingType::Sampler(SamplerBindingType::Filtering), - count: None, - }) - } - let main_bind_group = - device.create_bind_group_layout(&BindGroupLayoutDescriptor { - label: Some("bind group 0"), - entries: &main_bindings, - }); - - let sampler_bind_group = - device.create_bind_group_layout(&BindGroupLayoutDescriptor { - label: Some("bind group 1"), - entries: &sampler_bindings, - }); - - let bind_group_layout_refs = [&main_bind_group, &sampler_bind_group]; - - let layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - label: Some("shader pipeline layout"), - bind_group_layouts: &bind_group_layout_refs, - immediate_size: 0, - }); - - Self { - layout, - main_bind_group_layout: main_bind_group, - sampler_bind_group_layout: sampler_bind_group, - fragment_entry_name: shader_assembly.context.fragment.entry_points[0] - .name - .clone(), - vertex_entry_name: shader_assembly.context.vertex.entry_points[0] - .name - .clone(), - vertex, - fragment, - } - } - - pub fn create_pipeline( - &self, - device: &wgpu::Device, - framebuffer_format: TextureFormat, - cache: Option<&wgpu::PipelineCache>, - ) -> wgpu::RenderPipeline { - device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { - label: Some("Render Pipeline"), - layout: Some(&self.layout), - vertex: wgpu::VertexState { - module: &self.vertex, - entry_point: Some(&self.vertex_entry_name), - compilation_options: wgpu::PipelineCompilationOptions::default(), - buffers: &[VertexBufferLayout { - array_stride: std::mem::size_of::() - as wgpu::BufferAddress, - step_mode: wgpu::VertexStepMode::Vertex, - attributes: &[ - wgpu::VertexAttribute { - format: wgpu::VertexFormat::Float32x4, - offset: bytemuck::offset_of!(VertexInput, position) - as wgpu::BufferAddress, - shader_location: 0, - }, - wgpu::VertexAttribute { - format: wgpu::VertexFormat::Float32x2, - offset: bytemuck::offset_of!(VertexInput, texcoord) - as wgpu::BufferAddress, - shader_location: 1, - }, - ], - }], - }, - fragment: Some(wgpu::FragmentState { - module: &self.fragment, - entry_point: Some(&self.fragment_entry_name), - compilation_options: wgpu::PipelineCompilationOptions::default(), - targets: &[Some(wgpu::ColorTargetState { - format: framebuffer_format, - blend: None, - write_mask: wgpu::ColorWrites::ALL, - })], - }), - primitive: wgpu::PrimitiveState { - topology: wgpu::PrimitiveTopology::TriangleStrip, - strip_index_format: None, - front_face: wgpu::FrontFace::Ccw, - cull_mode: None, - unclipped_depth: false, - polygon_mode: wgpu::PolygonMode::Fill, - conservative: false, - }, - depth_stencil: None, - multisample: wgpu::MultisampleState { - count: 1, - mask: !0, - alpha_to_coverage_enabled: false, - }, - multiview_mask: None, - cache, - }) - } -} - -impl WgpuGraphicsPipeline { - pub fn new( - device: &wgpu::Device, - shader_assembly: &ShaderCompilerOutput, - reflection: &ShaderReflection, - render_pass_format: TextureFormat, - adapter_info: Option<&wgpu::AdapterInfo>, - bypass_cache: bool, - ) -> Self { - let cache = if bypass_cache { - None - } else { - let name = adapter_info - .and_then(wgpu::util::pipeline_cache_key) - .unwrap_or_else(|| String::from("wgpu")); - - cache_pipeline( - &name, - &[ - &shader_assembly.vertex.as_str(), - &shader_assembly.fragment.as_str(), - ], - |pipeline_data| { - let descriptor = wgpu::PipelineCacheDescriptor { - label: Some("librashader-wgpu"), - data: pipeline_data.as_deref(), - fallback: true, - }; - - let cache = unsafe { device.create_pipeline_cache(&descriptor) }; - Ok::<_, Infallible>(cache) - }, - |cache| Ok(cache.get_data()), - bypass_cache, - ) - .ok() - }; - - let layout = PipelineLayoutObjects::new(reflection, shader_assembly, device); - let mut render_pipelines = FastHashMap::default(); - render_pipelines.insert( - render_pass_format, - layout.create_pipeline(device, render_pass_format, cache.as_ref()), - ); - Self { - layout, - render_pipelines, - cache, - } - } - - pub fn has_format(&self, format: TextureFormat) -> bool { - self.render_pipelines.contains_key(&format) - } - - pub fn recompile(&mut self, device: &wgpu::Device, format: TextureFormat) { - let render_pipeline = - self.layout - .create_pipeline(device, format, self.cache.as_ref()); - self.render_pipelines.insert(format, render_pipeline); - } - - pub(crate) fn begin_rendering<'pass>( - &'pass self, - output: &RenderTarget<'pass, WgpuOutputView>, - cmd: &'pass mut CommandEncoder, - ) -> RenderPass<'pass> { - let Some(pipeline) = self - .render_pipelines - .get(&output.output.format) - .or_else(|| self.render_pipelines.values().next()) - else { - panic!("No available render pipelines found") - }; - - let mut render_pass = cmd.begin_render_pass(&RenderPassDescriptor { - label: Some("librashader"), - color_attachments: &[Some(RenderPassColorAttachment { - view: &output.output.view, - resolve_target: None, - ops: Operations { - load: wgpu::LoadOp::Clear(wgpu::Color { - r: 0.0, - g: 0.0, - b: 0.0, - a: 0.0, - }), - store: wgpu::StoreOp::Store, - }, - depth_slice: None, - })], - depth_stencil_attachment: None, - timestamp_writes: None, - occlusion_query_set: None, - multiview_mask: None, - }); - - render_pass.set_scissor_rect( - output.x as u32, - output.y as u32, - output.size.width, - output.size.height, - ); - - render_pass.set_viewport( - output.x, - output.y, - output.size.width as f32, - output.size.height as f32, - 0.0, - 1.0, - ); - - render_pass.set_pipeline(pipeline); - render_pass - } -} diff --git a/sugarloaf/src/components/filters/runtime/handle.rs b/sugarloaf/src/components/filters/runtime/handle.rs deleted file mode 100644 index 380cf233d4..0000000000 --- a/sugarloaf/src/components/filters/runtime/handle.rs +++ /dev/null @@ -1,21 +0,0 @@ -// This file was originally taken from https://github.com/SnowflakePowered/librashader -// SnowflakePowered/librashader is licensed under MPL-2.0 -// https://github.com/SnowflakePowered/librashader/blob/master/LICENSE.md - -use std::ops::Deref; - -pub enum Handle<'a, T> { - Borrowed(&'a T), - Owned(T), -} - -impl Deref for Handle<'_, T> { - type Target = T; - - fn deref(&self) -> &Self::Target { - match self { - Handle::Borrowed(r) => r, - Handle::Owned(r) => r, - } - } -} diff --git a/sugarloaf/src/components/filters/runtime/luts.rs b/sugarloaf/src/components/filters/runtime/luts.rs deleted file mode 100644 index 42eaf14c90..0000000000 --- a/sugarloaf/src/components/filters/runtime/luts.rs +++ /dev/null @@ -1,107 +0,0 @@ -// This file was originally taken from https://github.com/SnowflakePowered/librashader -// The file has changed to avoid use atomic reference counter of wgpu Device and Queue structs -// SnowflakePowered/librashader is licensed under MPL-2.0 -// https://github.com/SnowflakePowered/librashader/blob/master/LICENSE.md - -use crate::components::filters::runtime::mipmap::MipmapGen; -use crate::components::filters::runtime::samplers::SamplerSet; -use crate::components::filters::runtime::texture::InputImage; -use librashader_common::{Size, WrapMode}; -use librashader_presets::TextureMeta; -use librashader_runtime::image::Image; -use librashader_runtime::scaling::MipmapSize; -use std::sync::Arc; -use wgpu::TextureDescriptor; - -pub(crate) struct LutTexture(InputImage); -impl AsRef for LutTexture { - fn as_ref(&self) -> &InputImage { - &self.0 - } -} - -impl LutTexture { - pub fn new( - device: &wgpu::Device, - queue: &wgpu::Queue, - cmd: &mut wgpu::CommandEncoder, - image: Image, - config: &TextureMeta, - mipmapper: &mut MipmapGen, - sampler_set: &SamplerSet, - ) -> LutTexture { - let texture = device.create_texture(&TextureDescriptor { - label: Some(&config.name), - size: wgpu::Extent3d { - width: image.size.width, - height: image.size.height, - depth_or_array_layers: 1, - }, - mip_level_count: if config.mipmap { - image.size.calculate_miplevels() - } else { - 1 - }, - sample_count: 1, - dimension: wgpu::TextureDimension::D2, - format: wgpu::TextureFormat::Rgba8Unorm, - usage: wgpu::TextureUsages::TEXTURE_BINDING - | wgpu::TextureUsages::COPY_DST - // need render attachment for mipmaps... - | wgpu::TextureUsages::RENDER_ATTACHMENT, - view_formats: &[wgpu::TextureFormat::Rgba8Unorm], - }); - - queue.write_texture( - wgpu::TexelCopyTextureInfo { - texture: &texture, - mip_level: 0, - origin: wgpu::Origin3d::ZERO, - aspect: wgpu::TextureAspect::All, - }, - &image.bytes, - wgpu::TexelCopyBufferLayout { - offset: 0, - bytes_per_row: Some(4 * image.size.width), - rows_per_image: None, - }, - wgpu::Extent3d { - width: image.size.width, - height: image.size.height, - depth_or_array_layers: 1, - }, - ); - - if config.mipmap { - let wgpu_size = texture.size(); - let size = Size { - width: wgpu_size.width, - height: wgpu_size.height, - }; - - mipmapper.generate_mipmaps( - device, - cmd, - &texture, - &sampler_set.get( - WrapMode::ClampToEdge, - config.filter_mode, - config.filter_mode, - ), - size.calculate_miplevels(), - ); - } - - let view = texture.create_view(&wgpu::TextureViewDescriptor::default()); - - let image = InputImage { - image: Arc::new(texture), - view: Arc::new(view), - wrap_mode: config.wrap_mode, - filter_mode: config.filter_mode, - mip_filter: config.filter_mode, - }; - - Self(image) - } -} diff --git a/sugarloaf/src/components/filters/runtime/mipmap.rs b/sugarloaf/src/components/filters/runtime/mipmap.rs deleted file mode 100644 index 06d837849d..0000000000 --- a/sugarloaf/src/components/filters/runtime/mipmap.rs +++ /dev/null @@ -1,131 +0,0 @@ -// This file was originally taken from https://github.com/SnowflakePowered/librashader -// The file has changed to avoid use atomic reference counter of wgpu Device and Queue structs -// SnowflakePowered/librashader is licensed under MPL-2.0 -// https://github.com/SnowflakePowered/librashader/blob/master/LICENSE.md - -use librashader_common::map::FastHashMap; -use std::borrow::Cow; -use tracing::debug; - -pub struct MipmapGen { - shader: wgpu::ShaderModule, - pipeline_cache: FastHashMap, -} - -impl MipmapGen { - fn create_pipeline( - device: &wgpu::Device, - shader: &wgpu::ShaderModule, - format: wgpu::TextureFormat, - ) -> wgpu::RenderPipeline { - device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { - label: Some("blit"), - layout: None, - vertex: wgpu::VertexState { - module: shader, - entry_point: Some("vs_main"), - compilation_options: wgpu::PipelineCompilationOptions::default(), - buffers: &[], - }, - fragment: Some(wgpu::FragmentState { - module: shader, - entry_point: Some("fs_main"), - compilation_options: wgpu::PipelineCompilationOptions::default(), - targets: &[Some(format.into())], - }), - primitive: wgpu::PrimitiveState { - topology: wgpu::PrimitiveTopology::TriangleList, - ..Default::default() - }, - depth_stencil: None, - multisample: wgpu::MultisampleState::default(), - multiview_mask: None, - cache: None, - }) - } - pub fn new(device: &wgpu::Device) -> Self { - let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { - label: None, - source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!( - "../shader/blit.wgsl" - ))), - }); - - Self { - shader, - pipeline_cache: Default::default(), - } - } - - pub fn generate_mipmaps( - &mut self, - device: &wgpu::Device, - cmd: &mut wgpu::CommandEncoder, - texture: &wgpu::Texture, - sampler: &wgpu::Sampler, - miplevels: u32, - ) { - let format = texture.format(); - let pipeline = &*self.pipeline_cache.entry(format).or_insert_with(|| { - debug!("PipelineCache miss for texture format={:?}", format); - Self::create_pipeline(device, &self.shader, format) - }); - - let views = (0..miplevels) - .map(|mip| { - texture.create_view(&wgpu::TextureViewDescriptor { - label: Some("mip"), - format: None, - dimension: None, - aspect: wgpu::TextureAspect::All, - base_mip_level: mip, - mip_level_count: Some(1), - base_array_layer: 0, - array_layer_count: None, - ..Default::default() - }) - }) - .collect::>(); - - for target_mip in 1..miplevels as usize { - let bind_group_layout = pipeline.get_bind_group_layout(0); - let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { - layout: &bind_group_layout, - entries: &[ - wgpu::BindGroupEntry { - binding: 0, - resource: wgpu::BindingResource::TextureView( - &views[target_mip - 1], - ), - }, - wgpu::BindGroupEntry { - binding: 1, - resource: wgpu::BindingResource::Sampler(sampler), - }, - ], - label: None, - }); - - let mut pass = cmd.begin_render_pass(&wgpu::RenderPassDescriptor { - label: None, - color_attachments: &[Some(wgpu::RenderPassColorAttachment { - depth_slice: None, - view: &views[target_mip], - resolve_target: None, - ops: wgpu::Operations { - load: wgpu::LoadOp::Clear(wgpu::Color::BLACK), - store: wgpu::StoreOp::Store, - }, - })], - depth_stencil_attachment: None, - timestamp_writes: None, - occlusion_query_set: None, - multiview_mask: None, - }); - - pass.set_pipeline(pipeline); - pass.set_bind_group(0, &bind_group, &[]); - pass.draw(0..3, 0..1); - } - } -} diff --git a/sugarloaf/src/components/filters/runtime/mod.rs b/sugarloaf/src/components/filters/runtime/mod.rs deleted file mode 100644 index 12738bd3a1..0000000000 --- a/sugarloaf/src/components/filters/runtime/mod.rs +++ /dev/null @@ -1,162 +0,0 @@ -// This file was originally taken from https://github.com/SnowflakePowered/librashader -// The file has changed to avoid use atomic reference counter of wgpu Device and Queue structs -// SnowflakePowered/librashader is licensed under MPL-2.0 -// https://github.com/SnowflakePowered/librashader/blob/master/LICENSE.md - -//! librashader WGPU runtime -//! -//! This crate should not be used directly. -//! See [`librashader::runtime::wgpu`](https://docs.rs/librashader/latest/librashader/runtime/wgpu/index.html) instead. -#![deny(unsafe_op_in_unsafe_fn)] - -mod buffer; -mod draw_quad; -mod filter_chain; -mod filter_pass; -mod framebuffer; -mod graphics_pipeline; -mod handle; -mod luts; -mod mipmap; -mod samplers; -mod texture; -mod util; - -pub use filter_chain::FilterChain; -pub use framebuffer::WgpuOutputView; - -pub mod error; -pub mod options; - -/// Concatenates provided arrays. -#[macro_export] -macro_rules! concat_arrays { - ($( $array:expr ),*) => ({ - #[repr(C)] - struct ArrayConcatDecomposed(core::mem::ManuallyDrop<[T; 0]>, core::mem::ManuallyDrop, core::mem::ManuallyDrop); - - impl ArrayConcatDecomposed { - #[inline(always)] - const fn default() -> Self { - Self::new(core::mem::ManuallyDrop::new([]), []) - } - } - impl ArrayConcatDecomposed { - #[inline(always)] - const fn new(a: core::mem::ManuallyDrop, b: B) -> Self { - Self(core::mem::ManuallyDrop::new([]), a, core::mem::ManuallyDrop::new(b)) - } - #[inline(always)] - const fn concat(self, v: [T; N]) -> ArrayConcatDecomposed> { - ArrayConcatDecomposed::new(self.1, ArrayConcatDecomposed::new(self.2, v)) - } - } - - #[repr(C)] - union ArrayConcatComposed { - full: core::mem::ManuallyDrop<[T; N]>, - decomposed: core::mem::ManuallyDrop>, - } - - impl ArrayConcatComposed { - const HAVE_SAME_SIZE: bool = core::mem::size_of::<[T; N]>() == core::mem::size_of::(); - - const PANIC: bool = !["Size mismatch"][!Self::HAVE_SAME_SIZE as usize].is_empty(); - - #[inline(always)] - const fn have_same_size(&self) -> bool { - Self::PANIC - } - } - - let composed = ArrayConcatComposed { - decomposed: core::mem::ManuallyDrop::new( - ArrayConcatDecomposed::default()$(.concat($array))*, - ) - }; - - // Sanity check that composed's two fields are the same size - composed.have_same_size(); - - // SAFETY: Sizes of both fields in composed are the same so this assignment should be sound - core::mem::ManuallyDrop::into_inner(unsafe { composed.full }) - }); -} - -use librashader_runtime::impl_filter_chain_parameters; -impl_filter_chain_parameters!(FilterChain); - -#[inline] -pub fn format_from_image_to_texture( - format: &librashader_common::ImageFormat, -) -> Option { - match format { - librashader_common::ImageFormat::Unknown => None, - librashader_common::ImageFormat::R8Unorm => Some(wgpu::TextureFormat::R8Unorm), - librashader_common::ImageFormat::R8Uint => Some(wgpu::TextureFormat::R8Uint), - librashader_common::ImageFormat::R8Sint => Some(wgpu::TextureFormat::R8Sint), - librashader_common::ImageFormat::R8G8Unorm => Some(wgpu::TextureFormat::Rg8Unorm), - librashader_common::ImageFormat::R8G8Uint => Some(wgpu::TextureFormat::Rg8Uint), - librashader_common::ImageFormat::R8G8Sint => Some(wgpu::TextureFormat::Rg8Sint), - librashader_common::ImageFormat::R8G8B8A8Unorm => { - Some(wgpu::TextureFormat::Rgba8Unorm) - } - librashader_common::ImageFormat::R8G8B8A8Uint => { - Some(wgpu::TextureFormat::Rgba8Uint) - } - librashader_common::ImageFormat::R8G8B8A8Sint => { - Some(wgpu::TextureFormat::Rgba8Sint) - } - librashader_common::ImageFormat::R8G8B8A8Srgb => { - Some(wgpu::TextureFormat::Rgba8UnormSrgb) - } - librashader_common::ImageFormat::A2B10G10R10UnormPack32 => { - Some(wgpu::TextureFormat::Rgb10a2Unorm) - } - librashader_common::ImageFormat::A2B10G10R10UintPack32 => { - Some(wgpu::TextureFormat::Rgb10a2Uint) - } - librashader_common::ImageFormat::R16Uint => Some(wgpu::TextureFormat::R16Uint), - librashader_common::ImageFormat::R16Sint => Some(wgpu::TextureFormat::R16Sint), - librashader_common::ImageFormat::R16Sfloat => Some(wgpu::TextureFormat::R16Float), - librashader_common::ImageFormat::R16G16Uint => { - Some(wgpu::TextureFormat::Rg16Uint) - } - librashader_common::ImageFormat::R16G16Sint => { - Some(wgpu::TextureFormat::Rg16Sint) - } - librashader_common::ImageFormat::R16G16Sfloat => { - Some(wgpu::TextureFormat::Rg16Float) - } - librashader_common::ImageFormat::R16G16B16A16Uint => { - Some(wgpu::TextureFormat::Rgba16Uint) - } - librashader_common::ImageFormat::R16G16B16A16Sint => { - Some(wgpu::TextureFormat::Rgba16Sint) - } - librashader_common::ImageFormat::R16G16B16A16Sfloat => { - Some(wgpu::TextureFormat::Rgba16Float) - } - librashader_common::ImageFormat::R32Uint => Some(wgpu::TextureFormat::R32Uint), - librashader_common::ImageFormat::R32Sint => Some(wgpu::TextureFormat::R32Sint), - librashader_common::ImageFormat::R32Sfloat => Some(wgpu::TextureFormat::R32Float), - librashader_common::ImageFormat::R32G32Uint => { - Some(wgpu::TextureFormat::Rg32Uint) - } - librashader_common::ImageFormat::R32G32Sint => { - Some(wgpu::TextureFormat::Rg32Sint) - } - librashader_common::ImageFormat::R32G32Sfloat => { - Some(wgpu::TextureFormat::Rg32Float) - } - librashader_common::ImageFormat::R32G32B32A32Uint => { - Some(wgpu::TextureFormat::Rgba32Uint) - } - librashader_common::ImageFormat::R32G32B32A32Sint => { - Some(wgpu::TextureFormat::Rgba32Sint) - } - librashader_common::ImageFormat::R32G32B32A32Sfloat => { - Some(wgpu::TextureFormat::Rgba32Float) - } - } -} diff --git a/sugarloaf/src/components/filters/runtime/options.rs b/sugarloaf/src/components/filters/runtime/options.rs deleted file mode 100644 index 894012aadb..0000000000 --- a/sugarloaf/src/components/filters/runtime/options.rs +++ /dev/null @@ -1,23 +0,0 @@ -// This file was originally taken from https://github.com/SnowflakePowered/librashader -// SnowflakePowered/librashader is licensed under MPL-2.0 -// https://github.com/SnowflakePowered/librashader/blob/master/LICENSE.md - -//! wgpu shader runtime options. - -use librashader_runtime::impl_default_frame_options; -impl_default_frame_options!(FrameOptionsWgpu); - -/// Options for filter chain creation. -#[repr(C)] -#[derive(Default, Debug, Clone)] -pub struct FilterChainOptionsWgpu { - /// Whether or not to explicitly disable mipmap generation regardless of shader preset settings. - pub force_no_mipmaps: bool, - /// Enable the shader object cache. Shaders will be loaded from the cache - /// if this is enabled. - pub enable_cache: bool, - /// WGPU adapter info for use to determine the name of the pipeline cache index. - /// If this is not provided, then it will fallback to a default "wgpu" index, which - /// may clobber the cache for a different device using WGPU. - pub adapter_info: Option, -} diff --git a/sugarloaf/src/components/filters/runtime/samplers.rs b/sugarloaf/src/components/filters/runtime/samplers.rs deleted file mode 100644 index a1b6ca15f9..0000000000 --- a/sugarloaf/src/components/filters/runtime/samplers.rs +++ /dev/null @@ -1,100 +0,0 @@ -// This file was originally taken from https://github.com/SnowflakePowered/librashader -// The file has changed to avoid use atomic reference counter of wgpu Device and Queue structs -// SnowflakePowered/librashader is licensed under MPL-2.0 -// https://github.com/SnowflakePowered/librashader/blob/master/LICENSE.md - -use librashader_common::map::FastHashMap; -use librashader_common::{FilterMode, WrapMode}; -use std::sync::Arc; -use wgpu::{Sampler, SamplerBorderColor, SamplerDescriptor}; - -pub struct SamplerSet { - // todo: may need to deal with differences in mip filter. - samplers: FastHashMap<(WrapMode, FilterMode, FilterMode), Arc>, -} - -impl SamplerSet { - #[inline(always)] - pub fn get( - &self, - wrap: WrapMode, - filter: FilterMode, - mipmap: FilterMode, - ) -> Arc { - // eprintln!("{wrap}, {filter}, {mip}"); - // SAFETY: the sampler set is complete for the matrix - // wrap x filter x mipmap - unsafe { - Arc::clone( - self.samplers - .get(&(wrap, filter, mipmap)) - .unwrap_unchecked(), - ) - } - } - - pub fn new(device: &wgpu::Device) -> SamplerSet { - let mut samplers = FastHashMap::default(); - let wrap_modes = &[ - WrapMode::ClampToBorder, - WrapMode::ClampToEdge, - WrapMode::Repeat, - WrapMode::MirroredRepeat, - ]; - - let has_clamp_to_border = device - .features() - .contains(wgpu::Features::ADDRESS_MODE_CLAMP_TO_BORDER); - - for wrap_mode in wrap_modes { - for filter_mode in &[FilterMode::Linear, FilterMode::Nearest] { - for mipmap_filter in &[FilterMode::Linear, FilterMode::Nearest] { - let wgpu_wrap_mode = match wrap_mode { - WrapMode::ClampToBorder => { - if !has_clamp_to_border { - wgpu::AddressMode::ClampToEdge - } else { - wgpu::AddressMode::ClampToBorder - } - } - WrapMode::ClampToEdge => wgpu::AddressMode::ClampToEdge, - WrapMode::Repeat => wgpu::AddressMode::Repeat, - WrapMode::MirroredRepeat => wgpu::AddressMode::MirrorRepeat, - }; - - let wgpu_filter_mode = match filter_mode { - FilterMode::Linear => wgpu::FilterMode::Linear, - FilterMode::Nearest => wgpu::FilterMode::Nearest, - }; - - let wgpu_mipmap_filter = match mipmap_filter { - FilterMode::Linear => wgpu::MipmapFilterMode::Linear, - FilterMode::Nearest => wgpu::MipmapFilterMode::Nearest, - }; - - samplers.insert( - (*wrap_mode, *filter_mode, *mipmap_filter), - Arc::new(device.create_sampler(&SamplerDescriptor { - label: None, - address_mode_u: wgpu_wrap_mode, - address_mode_v: wgpu_wrap_mode, - address_mode_w: wgpu_wrap_mode, - mag_filter: wgpu_filter_mode, - min_filter: wgpu_filter_mode, - mipmap_filter: wgpu_mipmap_filter, - lod_min_clamp: 0.0, - lod_max_clamp: 1000.0, - compare: None, - anisotropy_clamp: 1, - border_color: Some(SamplerBorderColor::TransparentBlack), - })), - ); - } - } - } - - // assert all samplers were created. - assert_eq!(samplers.len(), wrap_modes.len() * 2 * 2); - SamplerSet { samplers } - } -} diff --git a/sugarloaf/src/components/filters/runtime/texture.rs b/sugarloaf/src/components/filters/runtime/texture.rs deleted file mode 100644 index d74ed94c16..0000000000 --- a/sugarloaf/src/components/filters/runtime/texture.rs +++ /dev/null @@ -1,195 +0,0 @@ -// This file was originally taken from https://github.com/SnowflakePowered/librashader -// The file has changed to avoid use atomic reference counter of wgpu Device and Queue structs -// SnowflakePowered/librashader is licensed under MPL-2.0 -// https://github.com/SnowflakePowered/librashader/blob/master/LICENSE.md - -use crate::components::filters::runtime::error::FilterChainError; -use crate::components::filters::runtime::mipmap::MipmapGen; -use crate::components::filters::runtime::{format_from_image_to_texture, WgpuOutputView}; -use librashader_common::{FilterMode, GetSize, ImageFormat, Size, WrapMode}; -use librashader_presets::Scale2D; -use librashader_runtime::scaling::{MipmapSize, ScaleFramebuffer, ViewportSize}; -use std::sync::Arc; -use wgpu::TextureFormat; - -pub struct OwnedImage { - pub image: Arc, - pub view: Arc, - pub max_miplevels: u32, - #[allow(dead_code)] - pub levels: u32, - pub size: Size, -} - -#[derive(Clone)] -pub struct InputImage { - pub image: Arc, - pub view: Arc, - pub wrap_mode: WrapMode, - pub filter_mode: FilterMode, - pub mip_filter: FilterMode, -} - -impl AsRef for InputImage { - fn as_ref(&self) -> &InputImage { - self - } -} - -impl OwnedImage { - pub fn new( - device: &wgpu::Device, - size: Size, - max_miplevels: u32, - format: TextureFormat, - ) -> Self { - let texture = device.create_texture(&wgpu::TextureDescriptor { - label: None, - size: wgpu::Extent3d { - width: size.width, - height: size.height, - depth_or_array_layers: 1, - }, - mip_level_count: std::cmp::min(max_miplevels, size.calculate_miplevels()), - sample_count: 1, - dimension: wgpu::TextureDimension::D2, - format, - usage: wgpu::TextureUsages::TEXTURE_BINDING - | wgpu::TextureUsages::RENDER_ATTACHMENT - | wgpu::TextureUsages::COPY_DST - | wgpu::TextureUsages::COPY_SRC, - view_formats: &[format], - }); - - let view = texture.create_view(&wgpu::TextureViewDescriptor { - label: None, - format: Some(format), - dimension: Some(wgpu::TextureViewDimension::D2), - aspect: wgpu::TextureAspect::All, - base_mip_level: 0, - mip_level_count: None, - base_array_layer: 0, - array_layer_count: None, - ..Default::default() - }); - - Self { - image: Arc::new(texture), - view: Arc::new(view), - max_miplevels, - levels: std::cmp::min(max_miplevels, size.calculate_miplevels()), - size, - } - } - - #[allow(clippy::too_many_arguments)] - pub fn scale( - &mut self, - device: &wgpu::Device, - scaling: Scale2D, - format: TextureFormat, - viewport_size: &Size, - source_size: &Size, - original_size: &Size, - mipmap: bool, - ) -> Size { - let size = source_size.scale_viewport( - scaling, - *viewport_size, - *original_size, - Some(device.limits().max_texture_dimension_2d), - ); - if self.size != size - || (mipmap && self.max_miplevels == 1) - || (!mipmap && self.max_miplevels != 1) - || format != self.image.format() - { - let mut new = OwnedImage::new(device, size, self.max_miplevels, format); - std::mem::swap(self, &mut new); - } - size - } - - pub(crate) fn as_input(&self, filter: FilterMode, wrap_mode: WrapMode) -> InputImage { - InputImage { - image: Arc::clone(&self.image), - view: Arc::clone(&self.view), - wrap_mode, - filter_mode: filter, - mip_filter: filter, - } - } - - pub fn copy_from( - &mut self, - cmd: &mut wgpu::CommandEncoder, - source: &wgpu::Texture, - device: &wgpu::Device, - ) { - let source_size = source.size(); - let source_size = Size { - width: source_size.width, - height: source_size.height, - }; - if source.format() != self.image.format() || self.size != source_size { - let mut new = - OwnedImage::new(device, source_size, self.max_miplevels, source.format()); - std::mem::swap(self, &mut new); - } - - cmd.copy_texture_to_texture( - source.as_image_copy(), - self.image.as_image_copy(), - source.size(), - ) - } - - pub fn clear(&self, cmd: &mut wgpu::CommandEncoder) { - cmd.clear_texture(&self.image, &wgpu::ImageSubresourceRange::default()); - } - pub fn generate_mipmaps( - &self, - device: &wgpu::Device, - cmd: &mut wgpu::CommandEncoder, - mipmapper: &mut MipmapGen, - sampler: &wgpu::Sampler, - ) { - mipmapper.generate_mipmaps(device, cmd, &self.image, sampler, self.max_miplevels); - } -} - -impl ScaleFramebuffer for OwnedImage { - type Error = FilterChainError; - type Context = wgpu::Device; - - fn scale( - &mut self, - scaling: Scale2D, - format: ImageFormat, - viewport_size: &Size, - source_size: &Size, - original_size: &Size, - should_mipmap: bool, - device: &Self::Context, - ) -> Result, Self::Error> { - let format: Option = format_from_image_to_texture(&format); - let format = format.unwrap_or(TextureFormat::Bgra8Unorm); - Ok(self.scale( - device, - scaling, - format, - viewport_size, - source_size, - original_size, - should_mipmap, - )) - } -} - -impl GetSize for WgpuOutputView<'_> { - type Error = std::convert::Infallible; - - fn size(&self) -> Result, Self::Error> { - Ok(self.size) - } -} diff --git a/sugarloaf/src/components/filters/runtime/util.rs b/sugarloaf/src/components/filters/runtime/util.rs deleted file mode 100644 index 00ec701c97..0000000000 --- a/sugarloaf/src/components/filters/runtime/util.rs +++ /dev/null @@ -1,19 +0,0 @@ -// This file was originally taken from https://github.com/SnowflakePowered/librashader -// SnowflakePowered/librashader is licensed under MPL-2.0 -// https://github.com/SnowflakePowered/librashader/blob/master/LICENSE.md - -use librashader_reflect::reflect::semantics::BindingStage; -use wgpu::ShaderStages; - -pub fn binding_stage_to_wgpu_stage(stage_mask: BindingStage) -> ShaderStages { - let mut mask = ShaderStages::empty(); - if stage_mask.contains(BindingStage::VERTEX) { - mask |= ShaderStages::VERTEX; - } - - if stage_mask.contains(BindingStage::FRAGMENT) { - mask |= ShaderStages::FRAGMENT; - } - - mask -}