rt: make scale framebuffers a lot nicer to use

This commit is contained in:
chyyran 2023-02-07 22:02:08 -05:00
parent 45dbdc6157
commit 06161b5aad
10 changed files with 95 additions and 61 deletions

View file

@ -26,7 +26,7 @@ use crate::{error, util, D3D11OutputView};
use librashader_reflect::reflect::presets::{CompilePresetTarget, ShaderPassArtifact};
use librashader_runtime::binding::{BindingUtil, TextureInput};
use librashader_runtime::quad::{QuadType, IDENTITY_MVP};
use librashader_runtime::scaling::scale_framebuffers;
use librashader_runtime::scaling::ScaleFramebuffer;
use librashader_runtime::uniforms::UniformStorage;
use rayon::prelude::*;
use windows::Win32::Graphics::Direct3D11::{
@ -455,12 +455,13 @@ impl FilterChainD3D11 {
let mut source = original.clone();
// rescale render buffers to ensure all bindings are valid.
scale_framebuffers::<(), _, _, _>(
OwnedFramebuffer::scale_framebuffers(
source.size(),
viewport.output.size,
&mut self.output_framebuffers,
&mut self.feedback_framebuffers,
passes,
None,
)?;
let passes_len = passes.len();

View file

@ -4,7 +4,7 @@ use crate::texture::D3D11InputView;
use crate::util::d3d11_get_closest_format;
use librashader_common::{ImageFormat, Size};
use librashader_presets::Scale2D;
use librashader_runtime::scaling::{MipmapSize, ScaleableFramebuffer, ViewportSize};
use librashader_runtime::scaling::{MipmapSize, ScaleFramebuffer, ViewportSize};
use windows::core::Interface;
use windows::Win32::Graphics::Direct3D::D3D_SRV_DIMENSION_TEXTURE2D;
use windows::Win32::Graphics::Direct3D11::{
@ -252,7 +252,7 @@ pub const fn default_viewport(size: Size<u32>) -> D3D11_VIEWPORT {
}
}
impl<T> ScaleableFramebuffer<T> for OwnedFramebuffer {
impl ScaleFramebuffer for OwnedFramebuffer {
type Error = FilterChainError;
type Context = ();
@ -263,7 +263,7 @@ impl<T> ScaleableFramebuffer<T> for OwnedFramebuffer {
viewport_size: &Size<u32>,
source_size: &Size<u32>,
should_mipmap: bool,
_context: Self::Context,
_context: &Self::Context,
) -> Result<Size<u32>, Self::Error> {
self.scale(scaling, format, viewport_size, source_size, should_mipmap)
}

View file

@ -46,7 +46,7 @@ use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT_UNKNOWN;
use windows::Win32::System::Threading::{CreateEventA, ResetEvent, WaitForSingleObject};
use windows::Win32::System::WindowsProgramming::INFINITE;
use librashader_runtime::scaling::{scale_framebuffers_with_context_callback, MipmapSize};
use librashader_runtime::scaling::{MipmapSize, ScaleFramebuffer};
use rayon::prelude::*;
const MIPMAP_RESERVED_WORKHEAP_DESCRIPTORS: usize = 1024;
@ -593,14 +593,13 @@ impl FilterChainD3D12 {
);
// rescale render buffers to ensure all bindings are valid.
scale_framebuffers_with_context_callback::<(), _, _, _, _>(
OwnedImage::scale_framebuffers(
source.size(),
viewport.output.size,
&mut self.output_framebuffers,
&mut self.feedback_framebuffers,
passes,
(),
|index: usize, pass: &FilterPass, output: &OwnedImage, feedback: &OwnedImage| {
Some(&mut |index, pass, output, feedback| {
// refresh inputs
self.common.feedback_textures[index] = Some(feedback.create_shader_resource_view(
&mut self.staging_heap,
@ -614,7 +613,7 @@ impl FilterChainD3D12 {
)?);
Ok(())
},
}),
)?;
let passes_len = passes.len();

View file

@ -5,7 +5,7 @@ use crate::util::d3d12_get_closest_format;
use crate::{error, util};
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
use librashader_presets::Scale2D;
use librashader_runtime::scaling::{MipmapSize, ScaleableFramebuffer, ViewportSize};
use librashader_runtime::scaling::{MipmapSize, ScaleFramebuffer, ViewportSize};
use std::ops::Deref;
use windows::Win32::Foundation::RECT;
use windows::Win32::Graphics::Direct3D12::{
@ -306,7 +306,7 @@ impl OwnedImage {
}
}
impl<T> ScaleableFramebuffer<T> for OwnedImage {
impl ScaleFramebuffer for OwnedImage {
type Error = FilterChainError;
type Context = ();
@ -317,7 +317,7 @@ impl<T> ScaleableFramebuffer<T> for OwnedImage {
viewport_size: &Size<u32>,
source_size: &Size<u32>,
should_mipmap: bool,
_context: Self::Context,
_context: &Self::Context,
) -> Result<Size<u32>, Self::Error> {
self.scale(scaling, format, viewport_size, source_size, should_mipmap)
}

View file

@ -21,7 +21,7 @@ use librashader_reflect::reflect::semantics::{BindingMeta, ShaderSemantics, Unif
use librashader_reflect::reflect::presets::{CompilePresetTarget, ShaderPassArtifact};
use librashader_reflect::reflect::ReflectShader;
use librashader_runtime::binding::BindingUtil;
use librashader_runtime::scaling::scale_framebuffers;
use librashader_runtime::scaling::ScaleFramebuffer;
use rustc_hash::FxHashMap;
use spirv_cross::spirv::Decoration;
use std::collections::VecDeque;
@ -380,12 +380,13 @@ impl<T: GLInterface> FilterChainImpl<T> {
let mut source = original;
// rescale render buffers to ensure all bindings are valid.
scale_framebuffers::<T::FramebufferInterface, _, _, _>(
<Framebuffer as ScaleFramebuffer<T::FramebufferInterface>>::scale_framebuffers(
source.image.size,
viewport.output.size,
&mut self.output_framebuffers,
&mut self.feedback_framebuffers,
passes,
None,
)?;
let passes_len = passes.len();

View file

@ -5,7 +5,7 @@ use crate::texture::InputTexture;
use gl::types::{GLenum, GLuint};
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
use librashader_presets::Scale2D;
use librashader_runtime::scaling::ScaleableFramebuffer;
use librashader_runtime::scaling::ScaleFramebuffer;
/// A handle to an OpenGL FBO and its backing texture with format and size information.
///
@ -94,7 +94,7 @@ impl Drop for Framebuffer {
}
}
//
impl<T: FramebufferInterface> ScaleableFramebuffer<T> for Framebuffer {
impl<T: FramebufferInterface> ScaleFramebuffer<T> for Framebuffer {
type Error = FilterChainError;
type Context = ();
@ -105,7 +105,7 @@ impl<T: FramebufferInterface> ScaleableFramebuffer<T> for Framebuffer {
viewport_size: &Size<u32>,
source_size: &Size<u32>,
should_mipmap: bool,
_context: Self::Context,
_context: &Self::Context,
) -> Result<Size<u32>> {
self.scale::<T>(scaling, format, viewport_size, source_size, should_mipmap)
}

View file

@ -30,7 +30,7 @@ use std::collections::VecDeque;
use std::path::Path;
use std::sync::Arc;
use librashader_runtime::scaling::scale_framebuffers_with_context_callback;
use librashader_runtime::scaling::ScaleFramebuffer;
use rayon::prelude::*;
/// A Vulkan device and metadata that is required by the shader runtime.
@ -614,27 +614,30 @@ impl FilterChainVulkan {
);
// rescale render buffers to ensure all bindings are valid.
scale_framebuffers_with_context_callback::<(), _, _, _, _>(
OwnedImage::scale_framebuffers_with_context(
source.image.size,
viewport.output.size,
&mut self.output_framebuffers,
&mut self.feedback_framebuffers,
passes,
Some(OwnedImageLayout {
&Some(OwnedImageLayout {
dst_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
dst_access: vk::AccessFlags::SHADER_READ,
src_stage: vk::PipelineStageFlags::TOP_OF_PIPE,
dst_stage: vk::PipelineStageFlags::FRAGMENT_SHADER,
cmd,
}),
|index: usize, pass: &FilterPass, output: &OwnedImage, feedback: &OwnedImage| {
Some(&mut |index: usize,
pass: &FilterPass,
output: &OwnedImage,
feedback: &OwnedImage| {
// refresh inputs
self.common.feedback_inputs[index] =
Some(feedback.as_input(pass.config.filter, pass.config.wrap_mode));
self.common.output_inputs[index] =
Some(output.as_input(pass.config.filter, pass.config.wrap_mode));
Ok(())
},
}),
)?;
let passes_len = passes.len();

View file

@ -8,7 +8,7 @@ use std::sync::Arc;
use crate::error::FilterChainError;
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
use librashader_presets::Scale2D;
use librashader_runtime::scaling::{MipmapSize, ScaleableFramebuffer, ViewportSize};
use librashader_runtime::scaling::{MipmapSize, ScaleFramebuffer, ViewportSize};
pub struct OwnedImage {
pub device: Arc<ash::Device>,
@ -20,7 +20,7 @@ pub struct OwnedImage {
pub levels: u32,
}
#[derive(Copy, Clone)]
#[derive(Clone)]
pub struct OwnedImageLayout {
pub(crate) dst_layout: vk::ImageLayout,
pub(crate) dst_access: vk::AccessFlags,
@ -536,7 +536,7 @@ impl AsRef<InputImage> for InputImage {
}
}
impl<T> ScaleableFramebuffer<T> for OwnedImage {
impl ScaleFramebuffer for OwnedImage {
type Error = FilterChainError;
type Context = Option<OwnedImageLayout>;
@ -547,7 +547,7 @@ impl<T> ScaleableFramebuffer<T> for OwnedImage {
viewport_size: &Size<u32>,
source_size: &Size<u32>,
should_mipmap: bool,
context: Self::Context,
context: &Self::Context,
) -> Result<Size<u32>, Self::Error> {
self.scale(
scaling,
@ -555,7 +555,7 @@ impl<T> ScaleableFramebuffer<T> for OwnedImage {
viewport_size,
source_size,
should_mipmap,
context,
context.clone(),
)
}
}

View file

@ -26,7 +26,8 @@ pub mod ringbuffer;
/// Generic implementation of semantics binding.
pub mod binding;
/// VBO helper utilities
/// VBO helper utilities.
pub mod quad;
/// Filter pass helpers and common traits.
pub mod filter_pass;

View file

@ -96,9 +96,9 @@ where
}
/// Trait for owned framebuffer objects that can be scaled.
pub trait ScaleableFramebuffer<T> {
pub trait ScaleFramebuffer<T = ()> {
type Error;
type Context: Copy;
type Context;
/// Scale the framebuffer according to the provided parameters, returning the new size.
fn scale(
&mut self,
@ -107,49 +107,76 @@ pub trait ScaleableFramebuffer<T> {
viewport_size: &Size<u32>,
source_size: &Size<u32>,
should_mipmap: bool,
context: Self::Context,
context: &Self::Context,
) -> Result<Size<u32>, Self::Error>;
}
/// Scale framebuffers according to the pass configs, source and viewport size.
#[inline(always)]
pub fn scale_framebuffers<T, F, E, P>(
source_size: Size<u32>,
viewport_size: Size<u32>,
output: &mut [F],
feedback: &mut [F],
passes: &[P],
) -> Result<(), E>
where
F: ScaleableFramebuffer<T, Context = (), Error = E>,
P: FilterPassMeta,
{
scale_framebuffers_with_context_callback(
source_size,
viewport_size,
output,
feedback,
passes,
(),
|_, _, _, _| Ok(()),
)
/// Scale framebuffers with default context.
#[inline(always)]
fn scale_framebuffers<P>(
source_size: Size<u32>,
viewport_size: Size<u32>,
output: &mut [Self],
feedback: &mut [Self],
passes: &[P],
callback: Option<&mut dyn FnMut(usize, &P, &Self, &Self) -> Result<(), Self::Error>>,
) -> Result<(), Self::Error>
where
Self: Sized,
Self::Context: Default,
P: FilterPassMeta,
{
scale_framebuffers_with_context_callback::<T, Self, Self::Error, Self::Context, _>(
source_size,
viewport_size,
output,
feedback,
passes,
&Self::Context::default(),
callback,
)
}
/// Scale framebuffers with user provided context.
#[inline(always)]
fn scale_framebuffers_with_context<P>(
source_size: Size<u32>,
viewport_size: Size<u32>,
output: &mut [Self],
feedback: &mut [Self],
passes: &[P],
context: &Self::Context,
callback: Option<&mut dyn FnMut(usize, &P, &Self, &Self) -> Result<(), Self::Error>>,
) -> Result<(), Self::Error>
where
Self: Sized,
P: FilterPassMeta,
{
scale_framebuffers_with_context_callback::<T, Self, Self::Error, Self::Context, _>(
source_size,
viewport_size,
output,
feedback,
passes,
context,
callback,
)
}
}
/// Scale framebuffers according to the pass configs, source and viewport size
/// passing a context into the scale function and a callback for each framebuffer rescale.
#[inline(always)]
pub fn scale_framebuffers_with_context_callback<T, F, E, C, P>(
fn scale_framebuffers_with_context_callback<T, F, E, C, P>(
source_size: Size<u32>,
viewport_size: Size<u32>,
output: &mut [F],
feedback: &mut [F],
passes: &[P],
context: C,
mut callback: impl FnMut(usize, &P, &F, &F) -> Result<(), E>,
context: &C,
mut callback: Option<&mut dyn FnMut(usize, &P, &F, &F) -> Result<(), E>>,
) -> Result<(), E>
where
F: ScaleableFramebuffer<T, Context = C, Error = E>,
C: Copy,
F: ScaleFramebuffer<T, Context = C, Error = E>,
P: FilterPassMeta,
{
assert_eq!(output.len(), feedback.len());
@ -180,7 +207,9 @@ where
target_size = next_size;
callback(index, pass, &output[index], &feedback[index])?;
if let Some(callback) = callback.as_mut() {
callback(index, pass, &output[index], &feedback[index])?;
}
}
Ok(())