From acc9bfeb5319eb7efb8914c5e293f6e917249f22 Mon Sep 17 00:00:00 2001 From: chyyran Date: Tue, 6 Feb 2024 01:58:39 -0500 Subject: [PATCH] rt(wgpu): add blocking submission API --- librashader-runtime-wgpu/src/filter_chain.rs | 49 +++++++++++++++++-- librashader-runtime-wgpu/src/options.rs | 8 +++ .../tests/hello_triangle.rs | 17 ++----- 3 files changed, 58 insertions(+), 16 deletions(-) diff --git a/librashader-runtime-wgpu/src/filter_chain.rs b/librashader-runtime-wgpu/src/filter_chain.rs index bc8b3fa..e80d785 100644 --- a/librashader-runtime-wgpu/src/filter_chain.rs +++ b/librashader-runtime-wgpu/src/filter_chain.rs @@ -11,6 +11,8 @@ use librashader_runtime::quad::QuadType; use librashader_runtime::uniforms::UniformStorage; use rustc_hash::FxHashMap; use std::collections::VecDeque; +use std::convert::Infallible; +use std::path::Path; use std::sync::Arc; @@ -31,7 +33,7 @@ use crate::framebuffer::OutputView; use crate::graphics_pipeline::WgpuGraphicsPipeline; use crate::luts::LutTexture; use crate::mipmap::MipmapGen; -use crate::options::FrameOptionsWGPU; +use crate::options::{FilterChainOptionsWGPU, FrameOptionsWGPU}; use crate::samplers::SamplerSet; use crate::texture::{InputImage, OwnedImage}; @@ -76,6 +78,46 @@ pub(crate) struct FilterCommon { } impl FilterChainWGPU { + /// Load the shader preset at the given path into a filter chain. + pub fn load_from_path( + path: impl AsRef, + device: Arc, + queue: Arc, + options: Option<&FilterChainOptionsWGPU>, + ) -> error::Result { + // load passes from preset + let preset = ShaderPreset::try_parse(path)?; + + 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: Arc, + queue: Arc, + options: Option<&FilterChainOptionsWGPU>, + ) -> error::Result { + let mut cmd = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { + label: Some("librashader load cmd"), + }); + let filter_chain = Self::load_from_preset_deferred( + preset, + Arc::clone(&device), + Arc::clone(&queue), + &mut cmd, + options, + )?; + + let cmd = cmd.finish(); + + // Wait for device + let index = queue.submit([cmd]); + device.poll(wgpu::Maintain::WaitForSubmissionIndex(index)); + + 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. /// @@ -84,10 +126,11 @@ impl FilterChainWGPU { /// 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_preset_deferred( + preset: ShaderPreset, device: Arc, queue: Arc, cmd: &mut wgpu::CommandEncoder, - preset: ShaderPreset, + options: Option<&FilterChainOptionsWGPU>, ) -> error::Result { let (passes, semantics) = compile_passes(preset.shaders, &preset.textures)?; @@ -157,7 +200,7 @@ impl FilterChainWGPU { output_framebuffers, feedback_framebuffers, history_framebuffers, - disable_mipmaps: false, // todo: force no mipmaps, + disable_mipmaps: options.map(|f| f.force_no_mipmaps).unwrap_or(false), mipmapper, }) } diff --git a/librashader-runtime-wgpu/src/options.rs b/librashader-runtime-wgpu/src/options.rs index 2ea17c8..656e5ef 100644 --- a/librashader-runtime-wgpu/src/options.rs +++ b/librashader-runtime-wgpu/src/options.rs @@ -8,3 +8,11 @@ pub struct FrameOptionsWGPU { /// -1 indicates that the frames are played in reverse order. pub frame_direction: i32, } + +/// 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, +} diff --git a/librashader-runtime-wgpu/tests/hello_triangle.rs b/librashader-runtime-wgpu/tests/hello_triangle.rs index 0aa3c98..f0219be 100644 --- a/librashader-runtime-wgpu/tests/hello_triangle.rs +++ b/librashader-runtime-wgpu/tests/hello_triangle.rs @@ -82,7 +82,7 @@ impl<'a> State<'a> { let size = window.inner_size(); let instance = wgpu::Instance::default(); - let surface = unsafe { instance.create_surface(window).unwrap() }; + let surface = instance.create_surface(window).unwrap(); // NOTE: could be none, see: https://sotrh.github.io/learn-wgpu/beginner/tutorial2-surface/#state-new let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { @@ -121,26 +121,17 @@ impl<'a> State<'a> { let device = Arc::new(device); let queue = Arc::new(queue); - let mut cmd = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { - label: Some("start encoder"), - }); - let preset = ShaderPreset::try_parse("../test/shaders_slang/crt/crt-royale.slangp").unwrap(); - let chain = FilterChainWGPU::load_from_preset_deferred( + let chain = FilterChainWGPU::load_from_preset( + preset, Arc::clone(&device), Arc::clone(&queue), - &mut cmd, - preset, + None, ) .unwrap(); - let cmd = cmd.finish(); - - let index = queue.submit([cmd]); - device.poll(Maintain::WaitForSubmissionIndex(index)); - let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { label: Some("Shader"), source: wgpu::ShaderSource::Wgsl(include_str!("../shader/triangle.wgsl").into()),