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 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<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
/// 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<Device>,
queue: Arc<wgpu::Queue>,
cmd: &mut wgpu::CommandEncoder,
preset: ShaderPreset,
options: Option<&FilterChainOptionsWGPU>,
) -> error::Result<FilterChainWGPU> {
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,
})
}

View file

@ -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,
}

View file

@ -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()),