diff --git a/librashader-runtime-d3d11/src/filter_chain.rs b/librashader-runtime-d3d11/src/filter_chain.rs index efbb4e9..065d4ca 100644 --- a/librashader-runtime-d3d11/src/filter_chain.rs +++ b/librashader-runtime-d3d11/src/filter_chain.rs @@ -65,7 +65,7 @@ pub(crate) struct Direct3D11 { pub context_is_deferred: bool, } -pub struct FilterCommon { +pub(crate) struct FilterCommon { pub(crate) d3d11: Direct3D11, pub(crate) luts: FxHashMap, pub samplers: SamplerSet, @@ -122,8 +122,8 @@ impl FilterChain { output_framebuffers.resize_with(filters.len(), || { OwnedFramebuffer::new( device, + ¤t_context, Size::new(1, 1), - 0, ImageFormat::R8G8B8A8Unorm, ) }); @@ -141,8 +141,8 @@ impl FilterChain { feedback_framebuffers.resize_with(filters.len(), || { OwnedFramebuffer::new( device, + ¤t_context, Size::new(1, 1), - 1, ImageFormat::R8G8B8A8Unorm, ) }); @@ -158,7 +158,9 @@ impl FilterChain { let luts = FilterChain::load_luts(device, ¤t_context, &preset.textures)?; let (history_framebuffers, history_textures) = - FilterChain::init_history(device, &filters)?; + FilterChain::init_history(device, + ¤t_context, + &filters)?; let draw_quad = DrawQuad::new(device, ¤t_context)?; @@ -315,7 +317,8 @@ impl FilterChain { fn init_history( device: &ID3D11Device, - filters: &[FilterPass], + context: &ID3D11DeviceContext, + filters: &Vec, ) -> error::Result<(VecDeque, Box<[Option]>)> { let mut required_images = 0; @@ -351,7 +354,7 @@ impl FilterChain { eprintln!("[history] using frame history with {required_images} images"); let mut framebuffers = VecDeque::with_capacity(required_images); framebuffers.resize_with(required_images, || { - OwnedFramebuffer::new(device, Size::new(1, 1), 1, ImageFormat::R8G8B8A8Unorm) + OwnedFramebuffer::new(device, context, Size::new(1, 1), ImageFormat::R8G8B8A8Unorm) }); let framebuffers = framebuffers @@ -487,6 +490,25 @@ impl FilterChain { self.draw_quad.bind_vertices(); + for ((texture, fbo), pass) in self + .common + .feedback_textures + .iter_mut() + .zip(self.feedback_framebuffers.iter()) + .zip(passes.iter()) + { + *texture = Some(Texture::from_framebuffer(fbo, pass.config.wrap_mode, pass.config.filter)?); + } + + for (texture, fbo) in self + .common + .history_textures + .iter_mut() + .zip(self.history_framebuffers.iter()) + { + *texture = Some(Texture::from_framebuffer(fbo, wrap_mode, filter)?); + } + let original = Texture { view: input.clone(), filter, @@ -565,19 +587,11 @@ impl FilterChain { &source, viewport.into(), )?; - // diverge so we don't need to clone output. break; } - // swap feedback framebuffers with output - for (output, feedback) in self - .output_framebuffers - .iter_mut() - .zip(self.feedback_framebuffers.iter_mut()) - { - std::mem::swap(output, feedback); - } + std::mem::swap(&mut self.output_framebuffers, &mut self.feedback_framebuffers); self.push_history(&input)?; diff --git a/librashader-runtime-d3d11/src/filter_pass.rs b/librashader-runtime-d3d11/src/filter_pass.rs index fb1cb6c..a8467ad 100644 --- a/librashader-runtime-d3d11/src/filter_pass.rs +++ b/librashader-runtime-d3d11/src/filter_pass.rs @@ -78,7 +78,7 @@ impl FilterPass { // framecount should be pre-modded fn build_semantics( &mut self, - _pass_index: usize, + pass_index: usize, parent: &FilterCommon, mvp: &[f32; 16], frame_count: u32, @@ -205,6 +205,7 @@ impl FilterPass { for (index, output) in parent.history_textures.iter().enumerate() { let Some(output) = output else { + eprintln!("no history"); continue; }; if let Some(binding) = self @@ -233,8 +234,10 @@ impl FilterPass { } // PassOutput - for (index, output) in parent.output_textures.iter().enumerate() { + for (index, output) in parent.output_textures[0..pass_index].iter().enumerate() { let Some(output) = output else { + eprintln!("no passoutput {index}"); + continue; }; if let Some(binding) = self @@ -264,6 +267,7 @@ impl FilterPass { // PassFeedback for (index, feedback) in parent.feedback_textures.iter().enumerate() { let Some(feedback) = feedback else { + eprintln!("no passfeedback {index}"); continue; }; if let Some(binding) = self @@ -356,6 +360,12 @@ impl FilterPass { ) -> error::Result<()> { let _device = &parent.d3d11.device; let context = &parent.d3d11.current_context; + + if self.config.mipmap_input { + unsafe { + context.GenerateMips(&source.view.handle); + } + } unsafe { context.IASetInputLayout(&self.vertex_layout); context.VSSetShader(&self.vertex_shader, None); diff --git a/librashader-runtime-d3d11/src/framebuffer.rs b/librashader-runtime-d3d11/src/framebuffer.rs index 1a139cf..347b2fe 100644 --- a/librashader-runtime-d3d11/src/framebuffer.rs +++ b/librashader-runtime-d3d11/src/framebuffer.rs @@ -5,15 +5,7 @@ use librashader_common::{ImageFormat, Size}; use librashader_presets::Scale2D; use windows::core::Interface; use windows::Win32::Graphics::Direct3D::D3D_SRV_DIMENSION_TEXTURE2D; -use windows::Win32::Graphics::Direct3D11::{ - ID3D11Device, ID3D11RenderTargetView, ID3D11ShaderResourceView, - ID3D11Texture2D, D3D11_BIND_RENDER_TARGET, D3D11_BIND_SHADER_RESOURCE, D3D11_CPU_ACCESS_WRITE, - D3D11_FORMAT_SUPPORT_RENDER_TARGET, D3D11_FORMAT_SUPPORT_SHADER_SAMPLE, - D3D11_FORMAT_SUPPORT_TEXTURE2D, D3D11_RENDER_TARGET_VIEW_DESC, D3D11_RENDER_TARGET_VIEW_DESC_0, - D3D11_RTV_DIMENSION_TEXTURE2D, D3D11_SHADER_RESOURCE_VIEW_DESC, - D3D11_SHADER_RESOURCE_VIEW_DESC_0, D3D11_TEX2D_RTV, D3D11_TEX2D_SRV, D3D11_TEXTURE2D_DESC, - D3D11_USAGE_DEFAULT, D3D11_VIEWPORT, -}; +use windows::Win32::Graphics::Direct3D11::{ID3D11Device, ID3D11RenderTargetView, ID3D11ShaderResourceView, ID3D11Texture2D, D3D11_BIND_RENDER_TARGET, D3D11_BIND_SHADER_RESOURCE, D3D11_CPU_ACCESS_WRITE, D3D11_FORMAT_SUPPORT_RENDER_TARGET, D3D11_FORMAT_SUPPORT_SHADER_SAMPLE, D3D11_FORMAT_SUPPORT_TEXTURE2D, D3D11_RENDER_TARGET_VIEW_DESC, D3D11_RENDER_TARGET_VIEW_DESC_0, D3D11_RTV_DIMENSION_TEXTURE2D, D3D11_SHADER_RESOURCE_VIEW_DESC, D3D11_SHADER_RESOURCE_VIEW_DESC_0, D3D11_TEX2D_RTV, D3D11_TEX2D_SRV, D3D11_TEXTURE2D_DESC, D3D11_USAGE_DEFAULT, D3D11_VIEWPORT, D3D11_RESOURCE_MISC_GENERATE_MIPS, D3D11_BOX, ID3D11DeviceContext}; use windows::Win32::Graphics::Dxgi::Common::{DXGI_FORMAT, DXGI_SAMPLE_DESC}; #[derive(Debug, Clone)] @@ -21,16 +13,16 @@ pub(crate) struct OwnedFramebuffer { pub texture: ID3D11Texture2D, pub size: Size, pub format: DXGI_FORMAT, - pub max_levels: u32, device: ID3D11Device, + context: ID3D11DeviceContext, is_raw: bool, } impl OwnedFramebuffer { pub fn new( device: &ID3D11Device, + context: &ID3D11DeviceContext, size: Size, - mip_levels: u32, format: ImageFormat, ) -> error::Result { unsafe { @@ -41,7 +33,7 @@ impl OwnedFramebuffer { | D3D11_FORMAT_SUPPORT_SHADER_SAMPLE.0 | D3D11_FORMAT_SUPPORT_RENDER_TARGET.0, ); - let desc = default_desc(size, format, mip_levels); + let desc = default_desc(size, format, 1); let texture = device.CreateTexture2D(&desc, None)?; Ok(OwnedFramebuffer { @@ -49,7 +41,7 @@ impl OwnedFramebuffer { size, format, device: device.clone(), - max_levels: mip_levels, + context: context.clone(), is_raw: false, }) } @@ -98,7 +90,7 @@ impl OwnedFramebuffer { | D3D11_FORMAT_SUPPORT_RENDER_TARGET.0, ); - let desc = default_desc(size, format, self.max_levels); + let desc = default_desc(size, format, 1); unsafe { let mut texture = self.device.CreateTexture2D(&desc, None)?; std::mem::swap(&mut self.texture, &mut texture); @@ -172,6 +164,26 @@ impl OwnedFramebuffer { self.init(image.size, ImageFormat::from(format))?; } + // unsafe { + // self.context.CopySubresourceRegion( + // &self.texture, + // 0, + // 0, + // 0, + // 0, + // &resource, + // 0, + // Some(&D3D11_BOX { + // left: 0, + // top: 0, + // front: 0, + // right: self.size.width, + // bottom: self.size.height, + // back: 1, + // }), + // ) + // } + // self.texture = resource; Ok(()) } @@ -197,7 +209,7 @@ fn default_desc(size: Size, format: DXGI_FORMAT, mip_levels: u32) -> D3D11_ Usage: D3D11_USAGE_DEFAULT, BindFlags: D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET, CPUAccessFlags: D3D11_CPU_ACCESS_WRITE, - MiscFlags: Default::default(), + MiscFlags: D3D11_RESOURCE_MISC_GENERATE_MIPS } } pub const fn default_viewport(size: Size) -> D3D11_VIEWPORT { diff --git a/librashader-runtime-d3d11/src/lib.rs b/librashader-runtime-d3d11/src/lib.rs index a27ff33..032730e 100644 --- a/librashader-runtime-d3d11/src/lib.rs +++ b/librashader-runtime-d3d11/src/lib.rs @@ -23,7 +23,7 @@ pub use texture::DxImageView; #[cfg(test)] mod tests { - + use crate::options::FilterChainOptions; use super::*; #[test] diff --git a/librashader-runtime-d3d11/src/texture.rs b/librashader-runtime-d3d11/src/texture.rs index 722e6b2..acfa41b 100644 --- a/librashader-runtime-d3d11/src/texture.rs +++ b/librashader-runtime-d3d11/src/texture.rs @@ -11,6 +11,7 @@ use windows::Win32::Graphics::Direct3D11::{ use windows::Win32::Graphics::Dxgi::Common::DXGI_SAMPLE_DESC; use crate::error::Result; +use crate::framebuffer::OwnedFramebuffer; #[derive(Debug, Clone)] pub struct DxImageView { @@ -18,14 +19,27 @@ pub struct DxImageView { pub size: Size, } #[derive(Debug, Clone)] -pub struct Texture { +pub(crate) struct Texture { pub view: DxImageView, pub filter: FilterMode, pub wrap_mode: WrapMode, } +impl Texture { + pub fn from_framebuffer(fbo: &OwnedFramebuffer, wrap_mode: WrapMode, filter: FilterMode) -> Result { + Ok(Texture { + view: DxImageView { + handle: fbo.create_shader_resource_view()?, + size: fbo.size, + }, + filter, + wrap_mode + }) + } +} + #[derive(Debug, Clone)] -pub struct LutTexture { +pub(crate) struct LutTexture { pub handle: ID3D11Texture2D, pub desc: D3D11_TEXTURE2D_DESC, pub image: Texture, diff --git a/librashader-runtime-d3d11/src/util.rs b/librashader-runtime-d3d11/src/util.rs index e767fa4..43bf411 100644 --- a/librashader-runtime-d3d11/src/util.rs +++ b/librashader-runtime-d3d11/src/util.rs @@ -118,7 +118,8 @@ pub fn d3d_compile_shader(source: &[u8], entry: &[u8], version: &[u8]) -> error: if cfg!(feature = "debug-shader") { D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION } else { - 0 + D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION + }, 0, &mut blob, diff --git a/librashader-runtime-gl/src/filter_chain/filter_impl.rs b/librashader-runtime-gl/src/filter_chain/filter_impl.rs index a55f7e3..3ff2ea2 100644 --- a/librashader-runtime-gl/src/filter_chain/filter_impl.rs +++ b/librashader-runtime-gl/src/filter_chain/filter_impl.rs @@ -535,16 +535,11 @@ impl FilterChainImpl { &source, viewport.into(), ); + self.common.output_textures[passes_len - 1] = viewport.output.as_texture(pass.config.filter, pass.config.wrap_mode); } // swap feedback framebuffers with output - for (output, feedback) in self - .output_framebuffers - .iter_mut() - .zip(self.feedback_framebuffers.iter_mut()) - { - std::mem::swap(output, feedback); - } + std::mem::swap(&mut self.output_framebuffers, &mut self.feedback_framebuffers); self.push_history(input)?; diff --git a/librashader-runtime-gl/src/filter_pass.rs b/librashader-runtime-gl/src/filter_pass.rs index 4477d53..aa0638a 100644 --- a/librashader-runtime-gl/src/filter_pass.rs +++ b/librashader-runtime-gl/src/filter_pass.rs @@ -45,6 +45,10 @@ impl FilterPass { ) { let framebuffer = output.framebuffer; + if self.config.mipmap_input { + T::BindTexture::gen_mipmaps(source); + } + unsafe { gl::BindFramebuffer(gl::FRAMEBUFFER, framebuffer.handle); gl::UseProgram(self.program); @@ -112,7 +116,7 @@ impl FilterPass { // framecount should be pre-modded fn build_semantics( &mut self, - _pass_index: usize, + pass_index: usize, parent: &FilterCommon, mvp: &[f32; 16], frame_count: u32, @@ -243,7 +247,7 @@ impl FilterPass { } // PassOutput - for (index, output) in parent.output_textures.iter().enumerate() { + for (index, output) in parent.output_textures[0..pass_index].iter().enumerate() { if !output.is_bound() { continue; } diff --git a/librashader-runtime-gl/src/gl/gl3/texture_bind.rs b/librashader-runtime-gl/src/gl/gl3/texture_bind.rs index b7bbd96..f3ede3b 100644 --- a/librashader-runtime-gl/src/gl/gl3/texture_bind.rs +++ b/librashader-runtime-gl/src/gl/gl3/texture_bind.rs @@ -18,4 +18,12 @@ impl BindTexture for Gl3BindTexture { ); } } + + fn gen_mipmaps(texture: &Texture) { + unsafe { + gl::BindTexture(gl::TEXTURE_2D, texture.image.handle); + gl::GenerateMipmap(gl::TEXTURE_2D); + gl::BindTexture(gl::TEXTURE_2D, 0); + } + } } diff --git a/librashader-runtime-gl/src/gl/gl46/texture_bind.rs b/librashader-runtime-gl/src/gl/gl46/texture_bind.rs index 87db8d2..5445048 100644 --- a/librashader-runtime-gl/src/gl/gl46/texture_bind.rs +++ b/librashader-runtime-gl/src/gl/gl46/texture_bind.rs @@ -16,4 +16,10 @@ impl BindTexture for Gl46BindTexture { ); } } + + fn gen_mipmaps(texture: &Texture) { + unsafe { + gl::GenerateTextureMipmap(texture.image.handle) + } + } } diff --git a/librashader-runtime-gl/src/gl/mod.rs b/librashader-runtime-gl/src/gl/mod.rs index 20396f5..b5876e2 100644 --- a/librashader-runtime-gl/src/gl/mod.rs +++ b/librashader-runtime-gl/src/gl/mod.rs @@ -60,6 +60,7 @@ pub trait FramebufferInterface { pub trait BindTexture { fn bind_texture(samplers: &SamplerSet, binding: &TextureBinding, texture: &Texture); + fn gen_mipmaps(texture: &Texture); } pub trait GLInterface {