From 2d6a967c7f5f697c66f1f5c91ae7d6c77751f8e0 Mon Sep 17 00:00:00 2001 From: chyyran Date: Sun, 29 Jan 2023 19:04:34 -0500 Subject: [PATCH] d3d11: generate mipmaps for inputs if requested --- librashader-runtime-d3d11/src/filter_chain.rs | 14 +++- librashader-runtime-d3d11/src/filter_pass.rs | 1 + librashader-runtime-d3d11/src/framebuffer.rs | 40 +++++---- .../src/hello_triangle.rs | 83 +++++++++++++++---- librashader-runtime-d3d11/src/lib.rs | 4 +- librashader-runtime-vk/src/lib.rs | 2 +- .../examples/example_win32_directx11/main.cpp | 2 +- 7 files changed, 112 insertions(+), 34 deletions(-) diff --git a/librashader-runtime-d3d11/src/filter_chain.rs b/librashader-runtime-d3d11/src/filter_chain.rs index f2c679d..e37a4e3 100644 --- a/librashader-runtime-d3d11/src/filter_chain.rs +++ b/librashader-runtime-d3d11/src/filter_chain.rs @@ -120,6 +120,7 @@ impl FilterChainD3D11 { ¤t_context, Size::new(1, 1), ImageFormat::R8G8B8A8Unorm, + false ) }); @@ -139,6 +140,7 @@ impl FilterChainD3D11 { ¤t_context, Size::new(1, 1), ImageFormat::R8G8B8A8Unorm, + false ) }); // resolve all results @@ -350,7 +352,7 @@ impl FilterChainD3D11 { // 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, context, Size::new(1, 1), ImageFormat::R8G8B8A8Unorm) + OwnedFramebuffer::new(device, context, Size::new(1, 1), ImageFormat::R8G8B8A8Unorm, false) }); let framebuffers = framebuffers @@ -463,15 +465,22 @@ impl FilterChainD3D11 { }; let mut source = original.clone(); + let mut iterator = passes.iter_mut().enumerate().peekable(); // rescale render buffers to ensure all bindings are valid. - for (index, pass) in passes.iter_mut().enumerate() { + while let Some((index, pass)) = iterator.next() { + let should_mipmap = iterator + .peek() + .map(|(_, p)| p.config.mipmap_input) + .unwrap_or(false); + self.output_framebuffers[index].scale( pass.config.scaling.clone(), pass.get_format(), &viewport.output.size, &original, &source, + should_mipmap )?; self.feedback_framebuffers[index].scale( @@ -480,6 +489,7 @@ impl FilterChainD3D11 { &viewport.output.size, &original, &source, + should_mipmap )?; } diff --git a/librashader-runtime-d3d11/src/filter_pass.rs b/librashader-runtime-d3d11/src/filter_pass.rs index a5c9477..70d5a3d 100644 --- a/librashader-runtime-d3d11/src/filter_pass.rs +++ b/librashader-runtime-d3d11/src/filter_pass.rs @@ -154,6 +154,7 @@ impl FilterPass { if self.config.mipmap_input && !parent.disable_mipmaps { unsafe { context.GenerateMips(&source.view.handle); + // context.GenerateMips(&original.view.handle); } } unsafe { diff --git a/librashader-runtime-d3d11/src/framebuffer.rs b/librashader-runtime-d3d11/src/framebuffer.rs index d3c7b11..9705858 100644 --- a/librashader-runtime-d3d11/src/framebuffer.rs +++ b/librashader-runtime-d3d11/src/framebuffer.rs @@ -4,7 +4,7 @@ use crate::texture::{D3D11InputView, InputTexture}; use crate::util::d3d11_get_closest_format; use librashader_common::{ImageFormat, Size}; use librashader_presets::Scale2D; -use librashader_runtime::scaling::ViewportSize; +use librashader_runtime::scaling::{calculate_miplevels, MipmapSize, ViewportSize}; use windows::core::Interface; use windows::Win32::Graphics::Direct3D::D3D_SRV_DIMENSION_TEXTURE2D; use windows::Win32::Graphics::Direct3D11::{ @@ -20,12 +20,13 @@ use windows::Win32::Graphics::Dxgi::Common::{DXGI_FORMAT, DXGI_SAMPLE_DESC}; #[derive(Debug, Clone)] pub(crate) struct OwnedFramebuffer { - pub texture: ID3D11Texture2D, - pub size: Size, - pub format: DXGI_FORMAT, + render: ID3D11Texture2D, + pub(crate) size: Size, + format: DXGI_FORMAT, device: ID3D11Device, context: ID3D11DeviceContext, is_raw: bool, + max_mipmap: u32, } impl OwnedFramebuffer { @@ -34,6 +35,7 @@ impl OwnedFramebuffer { context: &ID3D11DeviceContext, size: Size, format: ImageFormat, + mipmap: bool, ) -> error::Result { unsafe { let format = d3d11_get_closest_format( @@ -44,17 +46,18 @@ impl OwnedFramebuffer { | D3D11_FORMAT_SUPPORT_RENDER_TARGET.0, ); let desc = default_desc(size, format, 1); - let mut texture = None; - device.CreateTexture2D(&desc, None, Some(&mut texture))?; - assume_d3d11_init!(texture, "CreateTexture2D"); + let mut render = None; + device.CreateTexture2D(&desc, None, Some(&mut render))?; + assume_d3d11_init!(render, "CreateTexture2D"); Ok(OwnedFramebuffer { - texture, + render, size, format, device: device.clone(), context: context.clone(), is_raw: false, + max_mipmap: if mipmap { size.calculate_miplevels() } else { 1 }, }) } } @@ -66,6 +69,7 @@ impl OwnedFramebuffer { viewport_size: &Size, _original: &InputTexture, source: &InputTexture, + should_mipmap: bool, ) -> error::Result> { if self.is_raw { return Ok(self.size); @@ -73,8 +77,16 @@ impl OwnedFramebuffer { let size = source.view.size.scale_viewport(scaling, *viewport_size); - if self.size != size { + if self.size != size + || (should_mipmap && self.max_mipmap == 1) + || (!should_mipmap && self.max_mipmap != 1) + { self.size = size; + self.max_mipmap = if should_mipmap { + size.calculate_miplevels() + } else { + 1 + }; self.init( size, @@ -102,13 +114,13 @@ impl OwnedFramebuffer { ); // todo: fix mipmap handling - let desc = default_desc(size, format, 1); + let desc = default_desc(size, format, self.max_mipmap); unsafe { let mut texture = None; self.device .CreateTexture2D(&desc, None, Some(&mut texture))?; assume_d3d11_init!(mut texture, "CreateTexture2D"); - std::mem::swap(&mut self.texture, &mut texture); + std::mem::swap(&mut self.render, &mut texture); drop(texture) } self.format = format; @@ -121,7 +133,7 @@ impl OwnedFramebuffer { let mut srv = None; unsafe { self.device.CreateShaderResourceView( - &self.texture, + &self.render, Some(&D3D11_SHADER_RESOURCE_VIEW_DESC { Format: self.format, ViewDimension: D3D_SRV_DIMENSION_TEXTURE2D, @@ -143,7 +155,7 @@ impl OwnedFramebuffer { let mut rtv = None; unsafe { self.device.CreateRenderTargetView( - &self.texture, + &self.render, Some(&D3D11_RENDER_TARGET_VIEW_DESC { Format: self.format, ViewDimension: D3D11_RTV_DIMENSION_TEXTURE2D, @@ -188,7 +200,7 @@ impl OwnedFramebuffer { // will need a staging texture + full so might not be worth it. unsafe { self.context.CopySubresourceRegion( - &self.texture, + &self.render, 0, 0, 0, diff --git a/librashader-runtime-d3d11/src/hello_triangle.rs b/librashader-runtime-d3d11/src/hello_triangle.rs index cdc1d6c..9456d44 100644 --- a/librashader-runtime-d3d11/src/hello_triangle.rs +++ b/librashader-runtime-d3d11/src/hello_triangle.rs @@ -80,6 +80,16 @@ pub trait DXSample { fn window_size(&self) -> (i32, i32) { (WIDTH, HEIGHT) } + fn resize(&mut self, w: u32, h: u32) -> Result<()>; +} + +#[inline] +pub fn LOWORD(l: usize) -> u32 { + (l & 0xffff) as u32 +} +#[inline] +pub fn HIWORD(l: usize) -> u32 { + ((l >> 16) & 0xffff) as u32 } fn run_sample(mut sample: S) -> Result<()> @@ -168,6 +178,10 @@ fn sample_wndproc(sample: &mut S, message: u32, wparam: WPARAM) -> sample.render().unwrap(); true } + WM_SIZE => { + sample.resize(LOWORD(wparam.0), HIWORD(wparam.0)).unwrap(); + true + }, _ => false, } } @@ -190,6 +204,7 @@ extern "system" fn wndproc( unsafe { PostQuitMessage(0) }; LRESULT::default() } + _ => { let user_data = unsafe { GetWindowLongPtrA(window, GWLP_USERDATA) }; let sample = std::ptr::NonNull::::new(user_data as _); @@ -227,7 +242,7 @@ pub mod d3d11_hello_triangle { use crate::filter_chain::FilterChainD3D11; - use crate::options::FilterChainOptionsD3D11; + use crate::options::{FilterChainOptionsD3D11, FrameOptionsD3D11}; use crate::texture::D3D11InputView; use crate::D3D11OutputView; use librashader_common::{Size, Viewport}; @@ -256,8 +271,10 @@ pub mod d3d11_hello_triangle { pub frame_end: Instant, pub elapsed: f32, triangle_uniform_values: TriangleUniforms, - pub backbuffer: ID3D11Texture2D, - pub backbuffer_rtv: ID3D11RenderTargetView, + pub renderbuffer: ID3D11Texture2D, + pub renderbufffer_rtv: ID3D11RenderTargetView, + pub backbuffer: Option, + pub backbuffer_rtv: Option, pub viewport: D3D11_VIEWPORT, pub shader_output: Option, pub frame_count: usize, @@ -323,10 +340,24 @@ pub mod d3d11_hello_triangle { self.context.RSSetState(&raster_state); } + let (renderbuffer, render_rtv) = unsafe { + let mut renderbuffer = None; + let mut rtv = None; + let mut desc = Default::default(); + + backbuffer.GetDesc(&mut desc); + desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE; + + self.device.CreateTexture2D(&desc, None, Some(&mut renderbuffer))?; + let renderbuffer = renderbuffer.unwrap(); + self.device.CreateRenderTargetView(&renderbuffer, None, Some(&mut rtv))?; + (renderbuffer, rtv.unwrap()) + + }; self.resources = Some(Resources { swapchain, - backbuffer_rtv: rtv, - backbuffer, + backbuffer_rtv: Some(rtv), + backbuffer: Some(backbuffer), depth_buffer, depth_stencil_view, triangle_vertices: triangle_vbo, @@ -339,6 +370,8 @@ pub mod d3d11_hello_triangle { frame_start: Instant::now(), elapsed: 0f32, triangle_uniform_values: Default::default(), + renderbuffer, + renderbufffer_rtv: render_rtv, viewport: D3D11_VIEWPORT { TopLeftX: 0.0, TopLeftY: 0.0, @@ -354,6 +387,22 @@ pub mod d3d11_hello_triangle { Ok(()) } + fn resize(&mut self, w: u32, h: u32) -> Result<()> { + unsafe { + if let Some(resources) = self.resources.as_mut() { + drop(resources.backbuffer_rtv.take()); + drop(resources.backbuffer.take()); + resources.swapchain.ResizeBuffers(0, 0, + 0, DXGI_FORMAT_UNKNOWN, 0) + .unwrap_or_else(|f| eprintln!("{:?}", f)); + let (rtv, backbuffer) = create_rtv(&self.device, &resources.swapchain)?; + + resources.backbuffer = Some(backbuffer); + resources.backbuffer_rtv = Some(rtv); + } + } + Ok(()) + } fn render(&mut self) -> Result<()> { let Some(resources) = &mut self.resources else { return Ok(()); @@ -399,7 +448,7 @@ pub mod d3d11_hello_triangle { Some(&[resources.triangle_uniforms.clone()]), ); self.context.OMSetRenderTargets( - Some(&[resources.backbuffer_rtv.clone()]), + Some(&[resources.renderbufffer_rtv.clone()]), &resources.depth_stencil_view, ); self.context.RSSetViewports(Some(&[resources.viewport])) @@ -408,7 +457,7 @@ pub mod d3d11_hello_triangle { unsafe { let color = [0.3, 0.4, 0.6, 1.0]; self.context - .ClearRenderTargetView(&resources.backbuffer_rtv, color.as_ptr()); + .ClearRenderTargetView(&resources.renderbufffer_rtv, color.as_ptr()); self.context.ClearDepthStencilView( &resources.depth_stencil_view, D3D11_CLEAR_DEPTH.0, @@ -443,8 +492,11 @@ pub mod d3d11_hello_triangle { unsafe { let mut tex2d_desc = Default::default(); - resources.backbuffer.GetDesc(&mut tex2d_desc); - let mut backbuffer_copy = None; + resources.renderbuffer.GetDesc(&mut tex2d_desc); + let mut backbuffer_desc = Default::default(); + resources.backbuffer.as_ref().unwrap().GetDesc(&mut backbuffer_desc); + + let mut renderbuffer_copy = None; self.device.CreateTexture2D( &D3D11_TEXTURE2D_DESC { @@ -453,11 +505,11 @@ pub mod d3d11_hello_triangle { ..tex2d_desc }, None, - Some(&mut backbuffer_copy), + Some(&mut renderbuffer_copy), )?; - let backup = backbuffer_copy.unwrap(); + let backup = renderbuffer_copy.unwrap(); - self.context.CopyResource(&backup, &resources.backbuffer); + self.context.CopyResource(&backup, &resources.renderbuffer); let mut copy_srv = None; self.device.CreateShaderResourceView( @@ -494,6 +546,7 @@ pub mod d3d11_hello_triangle { Some(&mut rtv), )?; + // eprintln!("w: {} h: {}", backbuffer_desc.Width, backbuffer_desc.Height); self.filter .frame( D3D11InputView { @@ -508,10 +561,10 @@ pub mod d3d11_hello_triangle { y: resources.viewport.TopLeftY, output: D3D11OutputView { size: Size { - width: tex2d_desc.Width, - height: tex2d_desc.Height, + width: backbuffer_desc.Width, + height: backbuffer_desc.Height, }, - handle: resources.backbuffer_rtv.clone(), + handle: resources.backbuffer_rtv.as_ref().unwrap().clone(), }, mvp: None, }, diff --git a/librashader-runtime-d3d11/src/lib.rs b/librashader-runtime-d3d11/src/lib.rs index 1bb6895..e7a982f 100644 --- a/librashader-runtime-d3d11/src/lib.rs +++ b/librashader-runtime-d3d11/src/lib.rs @@ -34,7 +34,9 @@ mod tests { fn triangle_d3d11() { let sample = hello_triangle::d3d11_hello_triangle::Sample::new( "../test/slang-shaders/crt/crt-royale.slangp", - // "../test/basic.slangp", + // "../test/slang-shaders/presets/crt-geom-ntsc-upscale-sharp.slangp", + // "../test/slang-shaders/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp", + // "../test/null.slangp", Some(&FilterChainOptionsD3D11 { use_deferred_context: false, force_no_mipmaps: false, diff --git a/librashader-runtime-vk/src/lib.rs b/librashader-runtime-vk/src/lib.rs index 9625ee9..bdd9b2f 100644 --- a/librashader-runtime-vk/src/lib.rs +++ b/librashader-runtime-vk/src/lib.rs @@ -47,7 +47,7 @@ mod tests { let filter = FilterChainVulkan::load_from_path( &base, // "../test/slang-shaders/border/gameboy-player/gameboy-player-crt-royale.slangp", - "../test/slang-shaders/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp", + "../test/slang-shaders/bezel/Mega_Bezel/Presets/MBZ__2__ADV-NO-REFLECT.slangp", // "../test/basic.slangp", Some(&FilterChainOptionsVulkan { frames_in_flight: 3, diff --git a/test/capi-tests/imgui/examples/example_win32_directx11/main.cpp b/test/capi-tests/imgui/examples/example_win32_directx11/main.cpp index 472c74d..947dac6 100644 --- a/test/capi-tests/imgui/examples/example_win32_directx11/main.cpp +++ b/test/capi-tests/imgui/examples/example_win32_directx11/main.cpp @@ -66,7 +66,7 @@ int main(int, char**) auto libra = librashader_load_instance(); libra_shader_preset_t preset; auto error = libra.preset_create( - "../../../../../../slang-shaders/crt/crt-lottes.slangp", &preset); + "../../../../../../slang-shaders/crt/crt-royale.slangp", &preset); libra_d3d11_filter_chain_t filter_chain; filter_chain_d3d11_opt_t opt = {