From daf30c83c0145d56c7ed6258eb4bba79b6f908cf Mon Sep 17 00:00:00 2001 From: chyyran Date: Mon, 12 Feb 2024 01:56:39 -0500 Subject: [PATCH] rt: add `Rotation`, `TotalSubFrames`, `CurrentSubFrame` uniform semantics --- .../src/runtime/d3d11/filter_chain.rs | 7 ++ .../src/runtime/d3d12/filter_chain.rs | 7 ++ .../src/runtime/gl/filter_chain.rs | 7 ++ .../src/runtime/vk/filter_chain.rs | 10 +- librashader-capi/src/version.rs | 6 +- librashader-reflect/src/reflect/cross/mod.rs | 5 +- librashader-reflect/src/reflect/naga/mod.rs | 7 +- librashader-reflect/src/reflect/semantics.rs | 26 +++- librashader-runtime-d3d11/src/filter_chain.rs | 8 +- librashader-runtime-d3d11/src/filter_pass.rs | 25 ++-- librashader-runtime-d3d11/src/options.rs | 12 +- librashader-runtime-d3d12/src/filter_chain.rs | 9 +- librashader-runtime-d3d12/src/filter_pass.rs | 24 ++-- librashader-runtime-d3d12/src/options.rs | 12 +- .../src/filter_chain/filter_impl.rs | 8 +- librashader-runtime-gl/src/filter_pass.rs | 24 ++-- librashader-runtime-gl/src/options.rs | 12 +- librashader-runtime-vk/src/filter_chain.rs | 8 +- librashader-runtime-vk/src/filter_pass.rs | 24 ++-- librashader-runtime-vk/src/options.rs | 12 +- librashader-runtime-wgpu/src/filter_chain.rs | 8 +- librashader-runtime-wgpu/src/filter_pass.rs | 24 ++-- librashader-runtime-wgpu/src/options.rs | 12 +- librashader-runtime/src/binding.rs | 111 ++++++++++++++++-- 24 files changed, 280 insertions(+), 128 deletions(-) diff --git a/librashader-capi/src/runtime/d3d11/filter_chain.rs b/librashader-capi/src/runtime/d3d11/filter_chain.rs index 2ec3dcd..0873826 100644 --- a/librashader-capi/src/runtime/d3d11/filter_chain.rs +++ b/librashader-capi/src/runtime/d3d11/filter_chain.rs @@ -73,11 +73,18 @@ pub struct frame_d3d11_opt_t { /// The direction of rendering. /// -1 indicates that the frames are played in reverse order. pub frame_direction: i32, + /// The rotation of the output. 0 = 0deg, 1 = 90deg, 2 = 180deg, 4 = 270deg. + pub rotation: u32, + /// The total number of subframes ran. Default is 1. + pub total_subframes: u32, + // The current sub frame. Default is 1. + pub current_subframe: u32, } config_struct! { impl FrameOptions => frame_d3d11_opt_t { 0 => [clear_history, frame_direction]; + 1 => [rotation, total_subframes, current_subframe] } } diff --git a/librashader-capi/src/runtime/d3d12/filter_chain.rs b/librashader-capi/src/runtime/d3d12/filter_chain.rs index a0360af..872ab03 100644 --- a/librashader-capi/src/runtime/d3d12/filter_chain.rs +++ b/librashader-capi/src/runtime/d3d12/filter_chain.rs @@ -54,11 +54,18 @@ pub struct frame_d3d12_opt_t { /// The direction of rendering. /// -1 indicates that the frames are played in reverse order. pub frame_direction: i32, + /// The rotation of the output. 0 = 0deg, 1 = 90deg, 2 = 180deg, 4 = 270deg. + pub rotation: u32, + /// The total number of subframes ran. Default is 1. + pub total_subframes: u32, + // The current sub frame. Default is 1. + pub current_subframe: u32, } config_struct! { impl FrameOptions => frame_d3d12_opt_t { 0 => [clear_history, frame_direction]; + 1 => [rotation, total_subframes, current_subframe] } } diff --git a/librashader-capi/src/runtime/gl/filter_chain.rs b/librashader-capi/src/runtime/gl/filter_chain.rs index 407645c..f048b8b 100644 --- a/librashader-capi/src/runtime/gl/filter_chain.rs +++ b/librashader-capi/src/runtime/gl/filter_chain.rs @@ -64,11 +64,18 @@ pub struct frame_gl_opt_t { /// The direction of rendering. /// -1 indicates that the frames are played in reverse order. pub frame_direction: i32, + /// The rotation of the output. 0 = 0deg, 1 = 90deg, 2 = 180deg, 4 = 270deg. + pub rotation: u32, + /// The total number of subframes ran. Default is 1. + pub total_subframes: u32, + // The current sub frame. Default is 1. + pub current_subframe: u32, } config_struct! { impl FrameOptions => frame_gl_opt_t { 0 => [clear_history, frame_direction]; + 1 => [rotation, total_subframes, current_subframe] } } diff --git a/librashader-capi/src/runtime/vk/filter_chain.rs b/librashader-capi/src/runtime/vk/filter_chain.rs index f3af7d8..507dece 100644 --- a/librashader-capi/src/runtime/vk/filter_chain.rs +++ b/librashader-capi/src/runtime/vk/filter_chain.rs @@ -17,6 +17,7 @@ use librashader::runtime::{Size, Viewport}; use ash::vk; +use crate::LIBRASHADER_API_VERSION; pub use ash::vk::PFN_vkGetInstanceProcAddr; /// A Vulkan instance function loader that the Vulkan filter chain needs to be initialized with. @@ -87,17 +88,24 @@ impl From for VulkanInstance { #[derive(Default, Debug, Clone)] pub struct frame_vk_opt_t { /// The librashader API version. - pub version: usize, + pub version: LIBRASHADER_API_VERSION, /// Whether or not to clear the history buffers. pub clear_history: bool, /// The direction of rendering. /// -1 indicates that the frames are played in reverse order. pub frame_direction: i32, + /// The rotation of the output. 0 = 0deg, 1 = 90deg, 2 = 180deg, 4 = 270deg. + pub rotation: u32, + /// The total number of subframes ran. Default is 1. + pub total_subframes: u32, + // The current sub frame. Default is 1. + pub current_subframe: u32, } config_struct! { impl FrameOptions => frame_vk_opt_t { 0 => [clear_history, frame_direction]; + 1 => [rotation, total_subframes, current_subframe] } } diff --git a/librashader-capi/src/version.rs b/librashader-capi/src/version.rs index 86cf558..6090be5 100644 --- a/librashader-capi/src/version.rs +++ b/librashader-capi/src/version.rs @@ -13,7 +13,11 @@ pub type LIBRASHADER_ABI_VERSION = usize; /// versions must remain backwards compatible. /// ## API Versions /// - API version 0: 0.1.0 -pub const LIBRASHADER_CURRENT_VERSION: LIBRASHADER_API_VERSION = 0; +/// - API version 1: 0.2.0 +/// - Added rotation, total_subframes, current_subframes to frame options +/// - Added preset context API +/// - Added Metal runtime API +pub const LIBRASHADER_CURRENT_VERSION: LIBRASHADER_API_VERSION = 1; /// The current version of the librashader ABI. /// Used by the loader to check ABI compatibility. diff --git a/librashader-reflect/src/reflect/cross/mod.rs b/librashader-reflect/src/reflect/cross/mod.rs index c07a810..db2bf18 100644 --- a/librashader-reflect/src/reflect/cross/mod.rs +++ b/librashader-reflect/src/reflect/cross/mod.rs @@ -92,7 +92,10 @@ impl ValidateTypeSemantics for UniqueSemantics { UniqueSemantics::MVP => { matches!(ty, Type::Float { .. }) && vecsize == 4 && columns == 4 } - UniqueSemantics::FrameCount => { + UniqueSemantics::FrameCount + | UniqueSemantics::Rotation + | UniqueSemantics::TotalSubFrames + | UniqueSemantics::CurrentSubFrame => { matches!(ty, Type::UInt { .. }) && vecsize == 1 && columns == 1 } UniqueSemantics::FrameDirection => { diff --git a/librashader-reflect/src/reflect/naga/mod.rs b/librashader-reflect/src/reflect/naga/mod.rs index 485a06f..18d2dec 100644 --- a/librashader-reflect/src/reflect/naga/mod.rs +++ b/librashader-reflect/src/reflect/naga/mod.rs @@ -163,7 +163,10 @@ impl ValidateTypeSemantics<&TypeInner> for UniqueSemantics { }); } } - UniqueSemantics::FrameCount => { + UniqueSemantics::FrameCount + | UniqueSemantics::Rotation + | UniqueSemantics::CurrentSubFrame + | UniqueSemantics::TotalSubFrames => { // Uint32 == width 4 if matches!(ty, TypeInner::Scalar( Scalar { kind, width }) if *kind == ScalarKind::Uint && *width == 4) { @@ -174,7 +177,7 @@ impl ValidateTypeSemantics<&TypeInner> for UniqueSemantics { } } UniqueSemantics::FrameDirection => { - // Uint32 == width 4 + // iint32 == width 4 if matches!(ty, TypeInner::Scalar( Scalar { kind, width }) if *kind == ScalarKind::Sint && *width == 4) { return Some(TypeInfo { diff --git a/librashader-reflect/src/reflect/semantics.rs b/librashader-reflect/src/reflect/semantics.rs index aa08640..18bffa9 100644 --- a/librashader-reflect/src/reflect/semantics.rs +++ b/librashader-reflect/src/reflect/semantics.rs @@ -40,11 +40,18 @@ pub enum UniqueSemantics { /// The frame count, possibly with shader-defined modulo. FrameCount = 3, // int, frame direction - /// The frame direction. + /// The direction in time where frames are rendered FrameDirection = 4, + //int, rotation (glUniform1i(uni->rotation, retroarch_get_rotation());) + /// The rotation index (0 = 0deg, 1 = 90deg, 2 = 180deg, 3 = 270deg) + Rotation = 5, + /// Total number of subframes. + TotalSubFrames = 6, + /// The current subframe (default 1) + CurrentSubFrame = 7, /// A user defined float parameter. // float, user defined parameter, array - FloatParameter = 5, + FloatParameter = 8, } impl UniqueSemantics { @@ -64,6 +71,9 @@ impl UniqueSemantics { UniqueSemantics::FinalViewport => UniformType::Vec4, UniqueSemantics::FrameCount => UniformType::Unsigned, UniqueSemantics::FrameDirection => UniformType::Signed, + UniqueSemantics::Rotation => UniformType::Unsigned, + UniqueSemantics::TotalSubFrames => UniformType::Unsigned, + UniqueSemantics::CurrentSubFrame => UniformType::Unsigned, UniqueSemantics::FloatParameter => UniformType::Float, } } @@ -405,6 +415,18 @@ impl UniqueSemanticMap for FxHashMap { semantics: UniqueSemantics::FrameDirection, index: (), }), + "Rotation" => Some(Semantic { + semantics: UniqueSemantics::Rotation, + index: (), + }), + "TotalSubFrames" => Some(Semantic { + semantics: UniqueSemantics::TotalSubFrames, + index: (), + }), + "CurrentSubFrame" => Some(Semantic { + semantics: UniqueSemantics::TotalSubFrames, + index: (), + }), _ => None, }, Some(UniformSemantic::Unique(variable)) => Some(*variable), diff --git a/librashader-runtime-d3d11/src/filter_chain.rs b/librashader-runtime-d3d11/src/filter_chain.rs index d757a26..d609bc8 100644 --- a/librashader-runtime-d3d11/src/filter_chain.rs +++ b/librashader-runtime-d3d11/src/filter_chain.rs @@ -55,6 +55,7 @@ pub struct FilterChainD3D11 { feedback_framebuffers: Box<[OwnedImage]>, history_framebuffers: VecDeque, state: D3D11State, + default_options: FrameOptionsD3D11, } pub(crate) struct Direct3D11 { @@ -203,6 +204,7 @@ impl FilterChainD3D11 { draw_quad, }, state, + default_options: Default::default(), }) } } @@ -416,7 +418,7 @@ impl FilterChainD3D11 { return Ok(()); } - let frame_direction = options.map_or(1, |f| f.frame_direction); + let options = options.unwrap_or(&self.default_options); let filter = passes[0].config.filter; let wrap_mode = passes[0].config.wrap_mode; @@ -480,7 +482,7 @@ impl FilterChainD3D11 { index, &self.common, pass.config.get_frame_count(frame_count), - frame_direction, + options, viewport, &original, &source, @@ -509,7 +511,7 @@ impl FilterChainD3D11 { passes_len - 1, &self.common, pass.config.get_frame_count(frame_count), - frame_direction, + options, viewport, &original, &source, diff --git a/librashader-runtime-d3d11/src/filter_pass.rs b/librashader-runtime-d3d11/src/filter_pass.rs index f3eb22e..b96b919 100644 --- a/librashader-runtime-d3d11/src/filter_pass.rs +++ b/librashader-runtime-d3d11/src/filter_pass.rs @@ -1,5 +1,7 @@ use crate::filter_chain::FilterCommon; +use crate::options::FrameOptionsD3D11; use crate::texture::InputTexture; + use librashader_common::{ImageFormat, Size, Viewport}; use librashader_preprocess::ShaderSource; use librashader_presets::ShaderPassConfig; @@ -9,7 +11,7 @@ use librashader_reflect::reflect::semantics::{ use librashader_reflect::reflect::ShaderReflection; use rustc_hash::FxHashMap; -use librashader_runtime::binding::{BindSemantics, TextureInput}; +use librashader_runtime::binding::{BindSemantics, TextureInput, UniformInputs}; use librashader_runtime::filter_pass::FilterPassMeta; use librashader_runtime::quad::QuadType; use librashader_runtime::render_target::RenderTarget; @@ -100,7 +102,7 @@ impl FilterPass { parent: &FilterCommon, mvp: &[f32; 16], frame_count: u32, - frame_direction: i32, + options: &FrameOptionsD3D11, fb_size: Size, viewport_size: Size, mut descriptors: ( @@ -115,11 +117,16 @@ impl FilterPass { &parent.samplers, &mut self.uniform_storage, &mut descriptors, - mvp, - frame_count, - frame_direction, - fb_size, - viewport_size, + 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, + viewport_size, + }, original, source, &self.uniform_bindings, @@ -141,7 +148,7 @@ impl FilterPass { pass_index: usize, parent: &FilterCommon, frame_count: u32, - frame_direction: i32, + options: &FrameOptionsD3D11, viewport: &Viewport, original: &InputTexture, source: &InputTexture, @@ -168,7 +175,7 @@ impl FilterPass { parent, output.mvp, frame_count, - frame_direction, + options, output.output.size, viewport.output.size, descriptors, diff --git a/librashader-runtime-d3d11/src/options.rs b/librashader-runtime-d3d11/src/options.rs index bfd6d14..c8ad304 100644 --- a/librashader-runtime-d3d11/src/options.rs +++ b/librashader-runtime-d3d11/src/options.rs @@ -1,15 +1,7 @@ //! Direct3D 11 shader runtime options. -/// Options for each Direct3D 11 shader frame. -#[repr(C)] -#[derive(Default, Debug, Clone)] -pub struct FrameOptionsD3D11 { - /// Whether or not to clear the history buffers. - pub clear_history: bool, - /// The direction of rendering. - /// -1 indicates that the frames are played in reverse order. - pub frame_direction: i32, -} +use librashader_runtime::impl_default_frame_options; +impl_default_frame_options!(FrameOptionsD3D11); /// Options for Direct3D 11 filter chain creation. #[repr(C)] diff --git a/librashader-runtime-d3d12/src/filter_chain.rs b/librashader-runtime-d3d12/src/filter_chain.rs index cbf0a1f..f594743 100644 --- a/librashader-runtime-d3d12/src/filter_chain.rs +++ b/librashader-runtime-d3d12/src/filter_chain.rs @@ -77,6 +77,8 @@ pub struct FilterChainD3D12 { mipmap_heap: D3D12DescriptorHeap, disable_mipmaps: bool, + + default_options: FrameOptionsD3D12, } pub(crate) struct FilterCommon { @@ -360,6 +362,7 @@ impl FilterChainD3D12 { mipmap_heap, disable_mipmaps: options.map_or(false, |o| o.force_no_mipmaps), residuals, + default_options: Default::default(), }) } @@ -620,7 +623,7 @@ impl FilterChainD3D12 { return Ok(()); } - let frame_direction = options.map_or(1, |f| f.frame_direction); + let options = options.unwrap_or(&self.default_options); let max = std::cmp::min(self.passes.len(), self.common.config.passes_enabled); let passes = &mut self.passes[0..max]; @@ -734,7 +737,7 @@ impl FilterChainD3D12 { index, &self.common, pass.config.get_frame_count(frame_count), - frame_direction, + options, viewport, &original, &source, @@ -796,7 +799,7 @@ impl FilterChainD3D12 { passes_len - 1, &self.common, pass.config.get_frame_count(frame_count), - frame_direction, + options, viewport, &original, &source, diff --git a/librashader-runtime-d3d12/src/filter_pass.rs b/librashader-runtime-d3d12/src/filter_pass.rs index 63ec0cb..a4aa0f7 100644 --- a/librashader-runtime-d3d12/src/filter_pass.rs +++ b/librashader-runtime-d3d12/src/filter_pass.rs @@ -3,6 +3,7 @@ use crate::descriptor_heap::{D3D12DescriptorHeapSlot, ResourceWorkHeap, SamplerW use crate::error; use crate::filter_chain::FilterCommon; use crate::graphics_pipeline::D3D12GraphicsPipeline; +use crate::options::FrameOptionsD3D12; use crate::samplers::SamplerSet; use crate::texture::{D3D12OutputView, InputTexture}; use librashader_common::{ImageFormat, Size, Viewport}; @@ -10,7 +11,7 @@ use librashader_preprocess::ShaderSource; use librashader_presets::ShaderPassConfig; use librashader_reflect::reflect::semantics::{MemberOffset, TextureBinding, UniformBinding}; use librashader_reflect::reflect::ShaderReflection; -use librashader_runtime::binding::{BindSemantics, TextureInput}; +use librashader_runtime::binding::{BindSemantics, TextureInput, UniformInputs}; use librashader_runtime::filter_pass::FilterPassMeta; use librashader_runtime::quad::QuadType; use librashader_runtime::render_target::RenderTarget; @@ -93,7 +94,7 @@ impl FilterPass { parent: &FilterCommon, mvp: &[f32; 16], frame_count: u32, - frame_direction: i32, + options: &FrameOptionsD3D12, fb_size: Size, viewport_size: Size, original: &InputTexture, @@ -104,11 +105,16 @@ impl FilterPass { &parent.samplers, &mut self.uniform_storage, &mut (&mut self.texture_heap, &mut self.sampler_heap), - mvp, - frame_count, - frame_direction, - fb_size, - viewport_size, + 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, + viewport_size, + }, original, source, &self.uniform_bindings, @@ -135,7 +141,7 @@ impl FilterPass { pass_index: usize, parent: &FilterCommon, frame_count: u32, - frame_direction: i32, + options: &FrameOptionsD3D12, viewport: &Viewport, original: &InputTexture, source: &InputTexture, @@ -151,7 +157,7 @@ impl FilterPass { parent, output.mvp, frame_count, - frame_direction, + options, output.output.size, viewport.output.size, original, diff --git a/librashader-runtime-d3d12/src/options.rs b/librashader-runtime-d3d12/src/options.rs index ebbe0ab..633c421 100644 --- a/librashader-runtime-d3d12/src/options.rs +++ b/librashader-runtime-d3d12/src/options.rs @@ -1,15 +1,7 @@ //! Direct3D 12 shader runtime options. -/// Options for each Direct3D12 shader frame. -#[repr(C)] -#[derive(Default, Debug, Clone)] -pub struct FrameOptionsD3D12 { - /// Whether or not to clear the history buffers. - pub clear_history: bool, - /// The direction of rendering. - /// -1 indicates that the frames are played in reverse order. - pub frame_direction: i32, -} +use librashader_runtime::impl_default_frame_options; +impl_default_frame_options!(FrameOptionsD3D12); /// Options for Direct3D 12 filter chain creation. #[repr(C)] diff --git a/librashader-runtime-gl/src/filter_chain/filter_impl.rs b/librashader-runtime-gl/src/filter_chain/filter_impl.rs index 3561370..0705f3f 100644 --- a/librashader-runtime-gl/src/filter_chain/filter_impl.rs +++ b/librashader-runtime-gl/src/filter_chain/filter_impl.rs @@ -45,6 +45,7 @@ pub(crate) struct FilterChainImpl { output_framebuffers: Box<[GLFramebuffer]>, feedback_framebuffers: Box<[GLFramebuffer]>, history_framebuffers: VecDeque, + default_options: FrameOptionsGL, } pub(crate) struct FilterCommon { @@ -194,6 +195,7 @@ impl FilterChainImpl { feedback_textures, history_textures, }, + default_options: Default::default(), }) } @@ -288,7 +290,7 @@ impl FilterChainImpl { if passes.is_empty() { return Ok(()); } - let frame_direction = options.map_or(1, |f| f.frame_direction); + let options = options.unwrap_or(&self.default_options); // do not need to rebind FBO 0 here since first `draw` will // bind automatically. @@ -355,7 +357,7 @@ impl FilterChainImpl { index, &self.common, pass.config.get_frame_count(frame_count), - frame_direction, + options, viewport, &original, &source, @@ -378,7 +380,7 @@ impl FilterChainImpl { passes_len - 1, &self.common, pass.config.get_frame_count(frame_count), - frame_direction, + options, viewport, &original, &source, diff --git a/librashader-runtime-gl/src/filter_pass.rs b/librashader-runtime-gl/src/filter_pass.rs index 4a51bda..cd4555f 100644 --- a/librashader-runtime-gl/src/filter_pass.rs +++ b/librashader-runtime-gl/src/filter_pass.rs @@ -5,7 +5,7 @@ use librashader_common::{ImageFormat, Size, Viewport}; use librashader_preprocess::ShaderSource; use librashader_presets::ShaderPassConfig; use librashader_reflect::reflect::semantics::{MemberOffset, TextureBinding, UniformBinding}; -use librashader_runtime::binding::{BindSemantics, ContextOffset, TextureInput}; +use librashader_runtime::binding::{BindSemantics, ContextOffset, TextureInput, UniformInputs}; use librashader_runtime::filter_pass::FilterPassMeta; use librashader_runtime::render_target::RenderTarget; use rustc_hash::FxHashMap; @@ -13,6 +13,7 @@ use rustc_hash::FxHashMap; use crate::binding::{GlUniformBinder, GlUniformStorage, UniformLocation, VariableLocation}; use crate::filter_chain::FilterCommon; use crate::gl::{BindTexture, GLInterface, UboRing}; +use crate::options::FrameOptionsGL; use crate::samplers::SamplerSet; use crate::GLFramebuffer; @@ -80,7 +81,7 @@ impl FilterPass { pass_index: usize, parent: &FilterCommon, frame_count: u32, - frame_direction: i32, + options: &FrameOptionsGL, viewport: &Viewport<&GLFramebuffer>, original: &InputTexture, source: &InputTexture, @@ -102,7 +103,7 @@ impl FilterPass { parent, output.mvp, frame_count, - frame_direction, + options, framebuffer.size, viewport, original, @@ -163,7 +164,7 @@ impl FilterPass { parent: &FilterCommon, mvp: &[f32; 16], frame_count: u32, - frame_direction: i32, + options: &FrameOptionsGL, fb_size: Size, viewport: &Viewport<&GLFramebuffer>, original: &InputTexture, @@ -174,11 +175,16 @@ impl FilterPass { &parent.samplers, &mut self.uniform_storage, &mut (), - mvp, - frame_count, - frame_direction, - fb_size, - viewport.output.size, + 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, + viewport_size: viewport.output.size, + }, original, source, &self.uniform_bindings, diff --git a/librashader-runtime-gl/src/options.rs b/librashader-runtime-gl/src/options.rs index 493f6f0..3e12950 100644 --- a/librashader-runtime-gl/src/options.rs +++ b/librashader-runtime-gl/src/options.rs @@ -1,15 +1,7 @@ //! OpenGL shader runtime options. -/// Options for each OpenGL shader frame. -#[repr(C)] -#[derive(Default, Debug, Clone)] -pub struct FrameOptionsGL { - /// Whether or not to clear the history buffers. - pub clear_history: bool, - /// The direction of rendering. - /// -1 indicates that the frames are played in reverse order. - pub frame_direction: i32, -} +use librashader_runtime::impl_default_frame_options; +impl_default_frame_options!(FrameOptionsGL); /// Options for filter chain creation. #[repr(C)] diff --git a/librashader-runtime-vk/src/filter_chain.rs b/librashader-runtime-vk/src/filter_chain.rs index cbf739a..04e88c5 100644 --- a/librashader-runtime-vk/src/filter_chain.rs +++ b/librashader-runtime-vk/src/filter_chain.rs @@ -125,6 +125,7 @@ pub struct FilterChainVulkan { history_framebuffers: VecDeque, disable_mipmaps: bool, residuals: Box<[FrameResiduals]>, + default_options: FrameOptionsVulkan, } pub struct FilterMutable { @@ -402,6 +403,7 @@ impl FilterChainVulkan { history_framebuffers, residuals: intermediates.into_boxed_slice(), disable_mipmaps: options.map_or(false, |o| o.force_no_mipmaps), + default_options: Default::default(), }) } @@ -667,7 +669,7 @@ impl FilterChainVulkan { let passes_len = passes.len(); let (pass, last) = passes.split_at_mut(passes_len - 1); - let frame_direction = options.map_or(1, |f| f.frame_direction); + let options = options.unwrap_or(&self.default_options); self.common.draw_quad.bind_vbo_for_frame(cmd); for (index, pass) in pass.iter_mut().enumerate() { @@ -684,7 +686,7 @@ impl FilterChainVulkan { index, &self.common, pass.config.get_frame_count(frame_count), - frame_direction, + options, viewport, &original, &source, @@ -729,7 +731,7 @@ impl FilterChainVulkan { passes_len - 1, &self.common, pass.config.get_frame_count(frame_count), - frame_direction, + options, viewport, &original, &source, diff --git a/librashader-runtime-vk/src/filter_pass.rs b/librashader-runtime-vk/src/filter_pass.rs index 7516c3c..1577b36 100644 --- a/librashader-runtime-vk/src/filter_pass.rs +++ b/librashader-runtime-vk/src/filter_pass.rs @@ -2,6 +2,7 @@ use crate::filter_chain::FilterCommon; use crate::framebuffer::OutputImage; use crate::graphics_pipeline::VulkanGraphicsPipeline; use crate::memory::RawVulkanBuffer; +use crate::options::FrameOptionsVulkan; use crate::samplers::SamplerSet; use crate::texture::InputImage; use crate::{error, VulkanImage}; @@ -13,7 +14,7 @@ use librashader_reflect::reflect::semantics::{ BindingStage, MemberOffset, TextureBinding, UniformBinding, }; use librashader_reflect::reflect::ShaderReflection; -use librashader_runtime::binding::{BindSemantics, TextureInput}; +use librashader_runtime::binding::{BindSemantics, TextureInput, UniformInputs}; use librashader_runtime::filter_pass::FilterPassMeta; use librashader_runtime::quad::QuadType; use librashader_runtime::render_target::RenderTarget; @@ -91,7 +92,7 @@ impl FilterPass { pass_index: usize, parent: &FilterCommon, frame_count: u32, - frame_direction: i32, + options: &FrameOptionsVulkan, viewport: &Viewport, original: &InputImage, source: &InputImage, @@ -106,7 +107,7 @@ impl FilterPass { parent, output.mvp, frame_count, - frame_direction, + options, output.output.size, viewport.output.size, &mut descriptor, @@ -187,7 +188,7 @@ impl FilterPass { parent: &FilterCommon, mvp: &[f32; 16], frame_count: u32, - frame_direction: i32, + options: &FrameOptionsVulkan, fb_size: Size, viewport_size: Size, descriptor_set: &mut vk::DescriptorSet, @@ -199,11 +200,16 @@ impl FilterPass { &parent.samplers, &mut self.uniform_storage, descriptor_set, - mvp, - frame_count, - frame_direction, - fb_size, - viewport_size, + 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, + viewport_size, + }, original, source, &self.uniform_bindings, diff --git a/librashader-runtime-vk/src/options.rs b/librashader-runtime-vk/src/options.rs index c327173..9e3d389 100644 --- a/librashader-runtime-vk/src/options.rs +++ b/librashader-runtime-vk/src/options.rs @@ -1,15 +1,7 @@ //! Vulkan shader runtime options. -/// Options for each Vulkan shader frame. -#[repr(C)] -#[derive(Default, Debug, Clone)] -pub struct FrameOptionsVulkan { - /// Whether or not to clear the history buffers. - pub clear_history: bool, - /// The direction of rendering. - /// -1 indicates that the frames are played in reverse order. - pub frame_direction: i32, -} +use librashader_runtime::impl_default_frame_options; +impl_default_frame_options!(FrameOptionsVulkan); /// Options for filter chain creation. #[repr(C)] diff --git a/librashader-runtime-wgpu/src/filter_chain.rs b/librashader-runtime-wgpu/src/filter_chain.rs index ff560fe..b0dabef 100644 --- a/librashader-runtime-wgpu/src/filter_chain.rs +++ b/librashader-runtime-wgpu/src/filter_chain.rs @@ -59,6 +59,7 @@ pub struct FilterChainWgpu { history_framebuffers: VecDeque, disable_mipmaps: bool, mipmapper: MipmapGen, + default_frame_options: FrameOptionsWgpu, } pub struct FilterMutable { @@ -204,6 +205,7 @@ impl FilterChainWgpu { history_framebuffers, disable_mipmaps: options.map(|f| f.force_no_mipmaps).unwrap_or(false), mipmapper, + default_frame_options: Default::default(), }) } @@ -408,7 +410,7 @@ impl FilterChainWgpu { let passes_len = passes.len(); let (pass, last) = passes.split_at_mut(passes_len - 1); - let frame_direction = options.map_or(1, |f| f.frame_direction); + let options = options.unwrap_or(&self.default_frame_options); for (index, pass) in pass.iter_mut().enumerate() { let target = &self.output_framebuffers[index]; @@ -424,7 +426,7 @@ impl FilterChainWgpu { index, &self.common, pass.config.get_frame_count(frame_count), - frame_direction, + options, viewport, &original, &source, @@ -463,7 +465,7 @@ impl FilterChainWgpu { passes_len - 1, &self.common, pass.config.get_frame_count(frame_count), - frame_direction, + options, viewport, &original, &source, diff --git a/librashader-runtime-wgpu/src/filter_pass.rs b/librashader-runtime-wgpu/src/filter_pass.rs index 467dff8..697b63a 100644 --- a/librashader-runtime-wgpu/src/filter_pass.rs +++ b/librashader-runtime-wgpu/src/filter_pass.rs @@ -3,6 +3,7 @@ use crate::error; use crate::filter_chain::FilterCommon; use crate::framebuffer::WgpuOutputView; use crate::graphics_pipeline::WgpuGraphicsPipeline; +use crate::options::FrameOptionsWgpu; use crate::samplers::SamplerSet; use crate::texture::InputImage; use librashader_common::{ImageFormat, Size, Viewport}; @@ -12,7 +13,7 @@ use librashader_reflect::reflect::semantics::{ BindingStage, MemberOffset, TextureBinding, UniformBinding, }; use librashader_reflect::reflect::ShaderReflection; -use librashader_runtime::binding::{BindSemantics, TextureInput}; +use librashader_runtime::binding::{BindSemantics, TextureInput, UniformInputs}; use librashader_runtime::filter_pass::FilterPassMeta; use librashader_runtime::quad::QuadType; use librashader_runtime::render_target::RenderTarget; @@ -89,7 +90,7 @@ impl FilterPass { pass_index: usize, parent: &FilterCommon, frame_count: u32, - frame_direction: i32, + options: &FrameOptionsWgpu, viewport: &Viewport, original: &InputImage, source: &InputImage, @@ -104,7 +105,7 @@ impl FilterPass { parent, output.mvp, frame_count, - frame_direction, + options, output.output.size, viewport.output.size, original, @@ -198,7 +199,7 @@ impl FilterPass { parent: &FilterCommon, mvp: &[f32; 16], frame_count: u32, - frame_direction: i32, + options: &FrameOptionsWgpu, fb_size: Size, viewport_size: Size, original: &InputImage, @@ -211,11 +212,16 @@ impl FilterPass { &parent.samplers, &mut self.uniform_storage, &mut (main_heap, sampler_heap), - mvp, - frame_count, - frame_direction, - fb_size, - viewport_size, + 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, + viewport_size, + }, original, source, &self.uniform_bindings, diff --git a/librashader-runtime-wgpu/src/options.rs b/librashader-runtime-wgpu/src/options.rs index 255b5c3..4bbfa46 100644 --- a/librashader-runtime-wgpu/src/options.rs +++ b/librashader-runtime-wgpu/src/options.rs @@ -1,15 +1,7 @@ //! wgpu shader runtime options. -/// Options for each wgpu shader frame. -#[repr(C)] -#[derive(Default, Debug, Clone)] -pub struct FrameOptionsWgpu { - /// Whether or not to clear the history buffers. - pub clear_history: bool, - /// The direction of rendering. - /// -1 indicates that the frames are played in reverse order. - pub frame_direction: i32, -} +use librashader_runtime::impl_default_frame_options; +impl_default_frame_options!(FrameOptionsWgpu); /// Options for filter chain creation. #[repr(C)] diff --git a/librashader-runtime/src/binding.rs b/librashader-runtime/src/binding.rs index 678248b..672b3c0 100644 --- a/librashader-runtime/src/binding.rs +++ b/librashader-runtime/src/binding.rs @@ -49,6 +49,26 @@ where } } +/// Inputs to binding semantics +pub struct UniformInputs<'a> { + /// MVP + pub mvp: &'a [f32; 16], + /// FrameCount + pub frame_count: u32, + /// Rotation + pub rotation: u32, + /// TotalSubFrames + pub total_subframes: u32, + /// CurrentSubFrame + pub current_subframe: u32, + /// FrameDirection + pub frame_direction: i32, + /// OutputSize + pub framebuffer_size: Size, + /// FinalViewportSize + pub viewport_size: Size, +} + /// Trait that abstracts binding of semantics to shader uniforms. pub trait BindSemantics, U = Box<[u8]>, P = Box<[u8]>> where @@ -92,11 +112,7 @@ where sampler_set: &Self::SamplerSet, uniform_storage: &mut UniformStorage, descriptor_set: &mut Self::DescriptorSet<'a>, - mvp: &[f32; 16], - frame_count: u32, - frame_direction: i32, - framebuffer_size: Size, - viewport_size: Size, + uniform_inputs: UniformInputs<'_>, original: &Self::InputTexture, source: &Self::InputTexture, uniform_bindings: &HashMap, @@ -110,27 +126,66 @@ where ) { // Bind MVP if let Some(offset) = uniform_bindings.get(&UniqueSemantics::MVP.into()) { - uniform_storage.bind_mat4(offset.offset(), mvp, offset.context()); + uniform_storage.bind_mat4(offset.offset(), uniform_inputs.mvp, offset.context()); } // Bind OutputSize if let Some(offset) = uniform_bindings.get(&UniqueSemantics::Output.into()) { - uniform_storage.bind_vec4(offset.offset(), framebuffer_size, offset.context()); + uniform_storage.bind_vec4( + offset.offset(), + uniform_inputs.framebuffer_size, + offset.context(), + ); } // bind FinalViewportSize if let Some(offset) = uniform_bindings.get(&UniqueSemantics::FinalViewport.into()) { - uniform_storage.bind_vec4(offset.offset(), viewport_size, offset.context()); + uniform_storage.bind_vec4( + offset.offset(), + uniform_inputs.viewport_size, + offset.context(), + ); } // bind FrameCount if let Some(offset) = uniform_bindings.get(&UniqueSemantics::FrameCount.into()) { - uniform_storage.bind_scalar(offset.offset(), frame_count, offset.context()); + uniform_storage.bind_scalar( + offset.offset(), + uniform_inputs.frame_count, + offset.context(), + ); } // bind FrameDirection if let Some(offset) = uniform_bindings.get(&UniqueSemantics::FrameDirection.into()) { - uniform_storage.bind_scalar(offset.offset(), frame_direction, offset.context()); + uniform_storage.bind_scalar( + offset.offset(), + uniform_inputs.frame_direction, + offset.context(), + ); + } + + // bind Rotation + if let Some(offset) = uniform_bindings.get(&UniqueSemantics::Rotation.into()) { + uniform_storage.bind_scalar(offset.offset(), uniform_inputs.rotation, offset.context()); + } + + // bind TotalSubFrames + if let Some(offset) = uniform_bindings.get(&UniqueSemantics::TotalSubFrames.into()) { + uniform_storage.bind_scalar( + offset.offset(), + uniform_inputs.total_subframes, + offset.context(), + ); + } + + // bind CurrentSubFrames + if let Some(offset) = uniform_bindings.get(&UniqueSemantics::CurrentSubFrame.into()) { + uniform_storage.bind_scalar( + offset.offset(), + uniform_inputs.current_subframe, + offset.context(), + ); } // bind Original sampler @@ -149,7 +204,7 @@ where Self::bind_texture(descriptor_set, sampler_set, binding, source, device); } - // bind SourcelSize + // bind SourceSize if let Some(offset) = uniform_bindings.get(&TextureSemantics::Source.semantics(0).into()) { uniform_storage.bind_vec4(offset.offset(), source.size(), offset.context()); } @@ -330,3 +385,37 @@ impl BindingUtil for BindingMeta { required_images } } + +#[macro_export] +macro_rules! impl_default_frame_options { + ($ty:ident) => { + /// Options for each frame. + #[repr(C)] + #[derive(Debug, Clone)] + pub struct $ty { + /// Whether or not to clear the history buffers. + pub clear_history: bool, + /// The direction of rendering. + /// -1 indicates that the frames are played in reverse order. + pub frame_direction: i32, + /// The rotation of the output. 0 = 0deg, 1 = 90deg, 2 = 180deg, 4 = 270deg. + pub rotation: u32, + /// The total number of subframes ran. Default is 1. + pub total_subframes: u32, + // The current sub frame. Default is 1. + pub current_subframe: u32, + } + + impl Default for $ty { + fn default() -> Self { + Self { + clear_history: false, + frame_direction: 1, + rotation: 0, + total_subframes: 1, + current_subframe: 1, + } + } + } + }; +}