rt(wgpu): add blocking submission API

This commit is contained in:
chyyran 2024-02-06 01:58:39 -05:00 committed by Ronny Chan
parent 54e86e7b06
commit acc9bfeb53
3 changed files with 58 additions and 16 deletions

View file

@ -11,6 +11,8 @@ use librashader_runtime::quad::QuadType;
use librashader_runtime::uniforms::UniformStorage; use librashader_runtime::uniforms::UniformStorage;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::convert::Infallible;
use std::path::Path;
use std::sync::Arc; use std::sync::Arc;
@ -31,7 +33,7 @@ use crate::framebuffer::OutputView;
use crate::graphics_pipeline::WgpuGraphicsPipeline; use crate::graphics_pipeline::WgpuGraphicsPipeline;
use crate::luts::LutTexture; use crate::luts::LutTexture;
use crate::mipmap::MipmapGen; use crate::mipmap::MipmapGen;
use crate::options::FrameOptionsWGPU; use crate::options::{FilterChainOptionsWGPU, FrameOptionsWGPU};
use crate::samplers::SamplerSet; use crate::samplers::SamplerSet;
use crate::texture::{InputImage, OwnedImage}; use crate::texture::{InputImage, OwnedImage};
@ -76,6 +78,46 @@ pub(crate) struct FilterCommon {
} }
impl FilterChainWGPU { impl FilterChainWGPU {
/// Load the shader preset at the given path into a filter chain.
pub fn load_from_path(
path: impl AsRef<Path>,
device: Arc<Device>,
queue: Arc<wgpu::Queue>,
options: Option<&FilterChainOptionsWGPU>,
) -> error::Result<FilterChainWGPU> {
// 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<Device>,
queue: Arc<wgpu::Queue>,
options: Option<&FilterChainOptionsWGPU>,
) -> error::Result<FilterChainWGPU> {
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 /// 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. /// 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 /// 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). /// graphics queue. The command buffer must be completely executed before calling [`frame`](Self::frame).
pub fn load_from_preset_deferred( pub fn load_from_preset_deferred(
preset: ShaderPreset,
device: Arc<Device>, device: Arc<Device>,
queue: Arc<wgpu::Queue>, queue: Arc<wgpu::Queue>,
cmd: &mut wgpu::CommandEncoder, cmd: &mut wgpu::CommandEncoder,
preset: ShaderPreset, options: Option<&FilterChainOptionsWGPU>,
) -> error::Result<FilterChainWGPU> { ) -> error::Result<FilterChainWGPU> {
let (passes, semantics) = compile_passes(preset.shaders, &preset.textures)?; let (passes, semantics) = compile_passes(preset.shaders, &preset.textures)?;
@ -157,7 +200,7 @@ impl FilterChainWGPU {
output_framebuffers, output_framebuffers,
feedback_framebuffers, feedback_framebuffers,
history_framebuffers, history_framebuffers,
disable_mipmaps: false, // todo: force no mipmaps, disable_mipmaps: options.map(|f| f.force_no_mipmaps).unwrap_or(false),
mipmapper, mipmapper,
}) })
} }

View file

@ -8,3 +8,11 @@ pub struct FrameOptionsWGPU {
/// -1 indicates that the frames are played in reverse order. /// -1 indicates that the frames are played in reverse order.
pub frame_direction: i32, 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,
}

View file

@ -82,7 +82,7 @@ impl<'a> State<'a> {
let size = window.inner_size(); let size = window.inner_size();
let instance = wgpu::Instance::default(); 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 // NOTE: could be none, see: https://sotrh.github.io/learn-wgpu/beginner/tutorial2-surface/#state-new
let adapter = instance let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions { .request_adapter(&wgpu::RequestAdapterOptions {
@ -121,26 +121,17 @@ impl<'a> State<'a> {
let device = Arc::new(device); let device = Arc::new(device);
let queue = Arc::new(queue); let queue = Arc::new(queue);
let mut cmd = device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("start encoder"),
});
let preset = let preset =
ShaderPreset::try_parse("../test/shaders_slang/crt/crt-royale.slangp").unwrap(); 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(&device),
Arc::clone(&queue), Arc::clone(&queue),
&mut cmd, None,
preset,
) )
.unwrap(); .unwrap();
let cmd = cmd.finish();
let index = queue.submit([cmd]);
device.poll(Maintain::WaitForSubmissionIndex(index));
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: Some("Shader"), label: Some("Shader"),
source: wgpu::ShaderSource::Wgsl(include_str!("../shader/triangle.wgsl").into()), source: wgpu::ShaderSource::Wgsl(include_str!("../shader/triangle.wgsl").into()),