d3d11: generate mipmaps for inputs if requested

This commit is contained in:
chyyran 2023-01-29 19:04:34 -05:00
parent 8b6481abc1
commit 2d6a967c7f
7 changed files with 112 additions and 34 deletions

View file

@ -120,6 +120,7 @@ impl FilterChainD3D11 {
&current_context, &current_context,
Size::new(1, 1), Size::new(1, 1),
ImageFormat::R8G8B8A8Unorm, ImageFormat::R8G8B8A8Unorm,
false
) )
}); });
@ -139,6 +140,7 @@ impl FilterChainD3D11 {
&current_context, &current_context,
Size::new(1, 1), Size::new(1, 1),
ImageFormat::R8G8B8A8Unorm, ImageFormat::R8G8B8A8Unorm,
false
) )
}); });
// resolve all results // resolve all results
@ -350,7 +352,7 @@ impl FilterChainD3D11 {
// eprintln!("[history] using frame history with {required_images} images"); // eprintln!("[history] using frame history with {required_images} images");
let mut framebuffers = VecDeque::with_capacity(required_images); let mut framebuffers = VecDeque::with_capacity(required_images);
framebuffers.resize_with(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 let framebuffers = framebuffers
@ -463,15 +465,22 @@ impl FilterChainD3D11 {
}; };
let mut source = original.clone(); let mut source = original.clone();
let mut iterator = passes.iter_mut().enumerate().peekable();
// rescale render buffers to ensure all bindings are valid. // 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( self.output_framebuffers[index].scale(
pass.config.scaling.clone(), pass.config.scaling.clone(),
pass.get_format(), pass.get_format(),
&viewport.output.size, &viewport.output.size,
&original, &original,
&source, &source,
should_mipmap
)?; )?;
self.feedback_framebuffers[index].scale( self.feedback_framebuffers[index].scale(
@ -480,6 +489,7 @@ impl FilterChainD3D11 {
&viewport.output.size, &viewport.output.size,
&original, &original,
&source, &source,
should_mipmap
)?; )?;
} }

View file

@ -154,6 +154,7 @@ impl FilterPass {
if self.config.mipmap_input && !parent.disable_mipmaps { if self.config.mipmap_input && !parent.disable_mipmaps {
unsafe { unsafe {
context.GenerateMips(&source.view.handle); context.GenerateMips(&source.view.handle);
// context.GenerateMips(&original.view.handle);
} }
} }
unsafe { unsafe {

View file

@ -4,7 +4,7 @@ use crate::texture::{D3D11InputView, InputTexture};
use crate::util::d3d11_get_closest_format; use crate::util::d3d11_get_closest_format;
use librashader_common::{ImageFormat, Size}; use librashader_common::{ImageFormat, Size};
use librashader_presets::Scale2D; use librashader_presets::Scale2D;
use librashader_runtime::scaling::ViewportSize; use librashader_runtime::scaling::{calculate_miplevels, MipmapSize, ViewportSize};
use windows::core::Interface; use windows::core::Interface;
use windows::Win32::Graphics::Direct3D::D3D_SRV_DIMENSION_TEXTURE2D; use windows::Win32::Graphics::Direct3D::D3D_SRV_DIMENSION_TEXTURE2D;
use windows::Win32::Graphics::Direct3D11::{ use windows::Win32::Graphics::Direct3D11::{
@ -20,12 +20,13 @@ use windows::Win32::Graphics::Dxgi::Common::{DXGI_FORMAT, DXGI_SAMPLE_DESC};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub(crate) struct OwnedFramebuffer { pub(crate) struct OwnedFramebuffer {
pub texture: ID3D11Texture2D, render: ID3D11Texture2D,
pub size: Size<u32>, pub(crate) size: Size<u32>,
pub format: DXGI_FORMAT, format: DXGI_FORMAT,
device: ID3D11Device, device: ID3D11Device,
context: ID3D11DeviceContext, context: ID3D11DeviceContext,
is_raw: bool, is_raw: bool,
max_mipmap: u32,
} }
impl OwnedFramebuffer { impl OwnedFramebuffer {
@ -34,6 +35,7 @@ impl OwnedFramebuffer {
context: &ID3D11DeviceContext, context: &ID3D11DeviceContext,
size: Size<u32>, size: Size<u32>,
format: ImageFormat, format: ImageFormat,
mipmap: bool,
) -> error::Result<OwnedFramebuffer> { ) -> error::Result<OwnedFramebuffer> {
unsafe { unsafe {
let format = d3d11_get_closest_format( let format = d3d11_get_closest_format(
@ -44,17 +46,18 @@ impl OwnedFramebuffer {
| D3D11_FORMAT_SUPPORT_RENDER_TARGET.0, | D3D11_FORMAT_SUPPORT_RENDER_TARGET.0,
); );
let desc = default_desc(size, format, 1); let desc = default_desc(size, format, 1);
let mut texture = None; let mut render = None;
device.CreateTexture2D(&desc, None, Some(&mut texture))?; device.CreateTexture2D(&desc, None, Some(&mut render))?;
assume_d3d11_init!(texture, "CreateTexture2D"); assume_d3d11_init!(render, "CreateTexture2D");
Ok(OwnedFramebuffer { Ok(OwnedFramebuffer {
texture, render,
size, size,
format, format,
device: device.clone(), device: device.clone(),
context: context.clone(), context: context.clone(),
is_raw: false, is_raw: false,
max_mipmap: if mipmap { size.calculate_miplevels() } else { 1 },
}) })
} }
} }
@ -66,6 +69,7 @@ impl OwnedFramebuffer {
viewport_size: &Size<u32>, viewport_size: &Size<u32>,
_original: &InputTexture, _original: &InputTexture,
source: &InputTexture, source: &InputTexture,
should_mipmap: bool,
) -> error::Result<Size<u32>> { ) -> error::Result<Size<u32>> {
if self.is_raw { if self.is_raw {
return Ok(self.size); return Ok(self.size);
@ -73,8 +77,16 @@ impl OwnedFramebuffer {
let size = source.view.size.scale_viewport(scaling, *viewport_size); 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.size = size;
self.max_mipmap = if should_mipmap {
size.calculate_miplevels()
} else {
1
};
self.init( self.init(
size, size,
@ -102,13 +114,13 @@ impl OwnedFramebuffer {
); );
// todo: fix mipmap handling // todo: fix mipmap handling
let desc = default_desc(size, format, 1); let desc = default_desc(size, format, self.max_mipmap);
unsafe { unsafe {
let mut texture = None; let mut texture = None;
self.device self.device
.CreateTexture2D(&desc, None, Some(&mut texture))?; .CreateTexture2D(&desc, None, Some(&mut texture))?;
assume_d3d11_init!(mut texture, "CreateTexture2D"); assume_d3d11_init!(mut texture, "CreateTexture2D");
std::mem::swap(&mut self.texture, &mut texture); std::mem::swap(&mut self.render, &mut texture);
drop(texture) drop(texture)
} }
self.format = format; self.format = format;
@ -121,7 +133,7 @@ impl OwnedFramebuffer {
let mut srv = None; let mut srv = None;
unsafe { unsafe {
self.device.CreateShaderResourceView( self.device.CreateShaderResourceView(
&self.texture, &self.render,
Some(&D3D11_SHADER_RESOURCE_VIEW_DESC { Some(&D3D11_SHADER_RESOURCE_VIEW_DESC {
Format: self.format, Format: self.format,
ViewDimension: D3D_SRV_DIMENSION_TEXTURE2D, ViewDimension: D3D_SRV_DIMENSION_TEXTURE2D,
@ -143,7 +155,7 @@ impl OwnedFramebuffer {
let mut rtv = None; let mut rtv = None;
unsafe { unsafe {
self.device.CreateRenderTargetView( self.device.CreateRenderTargetView(
&self.texture, &self.render,
Some(&D3D11_RENDER_TARGET_VIEW_DESC { Some(&D3D11_RENDER_TARGET_VIEW_DESC {
Format: self.format, Format: self.format,
ViewDimension: D3D11_RTV_DIMENSION_TEXTURE2D, ViewDimension: D3D11_RTV_DIMENSION_TEXTURE2D,
@ -188,7 +200,7 @@ impl OwnedFramebuffer {
// will need a staging texture + full so might not be worth it. // will need a staging texture + full so might not be worth it.
unsafe { unsafe {
self.context.CopySubresourceRegion( self.context.CopySubresourceRegion(
&self.texture, &self.render,
0, 0,
0, 0,
0, 0,

View file

@ -80,6 +80,16 @@ pub trait DXSample {
fn window_size(&self) -> (i32, i32) { fn window_size(&self) -> (i32, i32) {
(WIDTH, HEIGHT) (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<S>(mut sample: S) -> Result<()> fn run_sample<S>(mut sample: S) -> Result<()>
@ -168,6 +178,10 @@ fn sample_wndproc<S: DXSample>(sample: &mut S, message: u32, wparam: WPARAM) ->
sample.render().unwrap(); sample.render().unwrap();
true true
} }
WM_SIZE => {
sample.resize(LOWORD(wparam.0), HIWORD(wparam.0)).unwrap();
true
},
_ => false, _ => false,
} }
} }
@ -190,6 +204,7 @@ extern "system" fn wndproc<S: DXSample>(
unsafe { PostQuitMessage(0) }; unsafe { PostQuitMessage(0) };
LRESULT::default() LRESULT::default()
} }
_ => { _ => {
let user_data = unsafe { GetWindowLongPtrA(window, GWLP_USERDATA) }; let user_data = unsafe { GetWindowLongPtrA(window, GWLP_USERDATA) };
let sample = std::ptr::NonNull::<S>::new(user_data as _); let sample = std::ptr::NonNull::<S>::new(user_data as _);
@ -227,7 +242,7 @@ pub mod d3d11_hello_triangle {
use crate::filter_chain::FilterChainD3D11; use crate::filter_chain::FilterChainD3D11;
use crate::options::FilterChainOptionsD3D11; use crate::options::{FilterChainOptionsD3D11, FrameOptionsD3D11};
use crate::texture::D3D11InputView; use crate::texture::D3D11InputView;
use crate::D3D11OutputView; use crate::D3D11OutputView;
use librashader_common::{Size, Viewport}; use librashader_common::{Size, Viewport};
@ -256,8 +271,10 @@ pub mod d3d11_hello_triangle {
pub frame_end: Instant, pub frame_end: Instant,
pub elapsed: f32, pub elapsed: f32,
triangle_uniform_values: TriangleUniforms, triangle_uniform_values: TriangleUniforms,
pub backbuffer: ID3D11Texture2D, pub renderbuffer: ID3D11Texture2D,
pub backbuffer_rtv: ID3D11RenderTargetView, pub renderbufffer_rtv: ID3D11RenderTargetView,
pub backbuffer: Option<ID3D11Texture2D>,
pub backbuffer_rtv: Option<ID3D11RenderTargetView>,
pub viewport: D3D11_VIEWPORT, pub viewport: D3D11_VIEWPORT,
pub shader_output: Option<ID3D11Texture2D>, pub shader_output: Option<ID3D11Texture2D>,
pub frame_count: usize, pub frame_count: usize,
@ -323,10 +340,24 @@ pub mod d3d11_hello_triangle {
self.context.RSSetState(&raster_state); 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 { self.resources = Some(Resources {
swapchain, swapchain,
backbuffer_rtv: rtv, backbuffer_rtv: Some(rtv),
backbuffer, backbuffer: Some(backbuffer),
depth_buffer, depth_buffer,
depth_stencil_view, depth_stencil_view,
triangle_vertices: triangle_vbo, triangle_vertices: triangle_vbo,
@ -339,6 +370,8 @@ pub mod d3d11_hello_triangle {
frame_start: Instant::now(), frame_start: Instant::now(),
elapsed: 0f32, elapsed: 0f32,
triangle_uniform_values: Default::default(), triangle_uniform_values: Default::default(),
renderbuffer,
renderbufffer_rtv: render_rtv,
viewport: D3D11_VIEWPORT { viewport: D3D11_VIEWPORT {
TopLeftX: 0.0, TopLeftX: 0.0,
TopLeftY: 0.0, TopLeftY: 0.0,
@ -354,6 +387,22 @@ pub mod d3d11_hello_triangle {
Ok(()) 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<()> { fn render(&mut self) -> Result<()> {
let Some(resources) = &mut self.resources else { let Some(resources) = &mut self.resources else {
return Ok(()); return Ok(());
@ -399,7 +448,7 @@ pub mod d3d11_hello_triangle {
Some(&[resources.triangle_uniforms.clone()]), Some(&[resources.triangle_uniforms.clone()]),
); );
self.context.OMSetRenderTargets( self.context.OMSetRenderTargets(
Some(&[resources.backbuffer_rtv.clone()]), Some(&[resources.renderbufffer_rtv.clone()]),
&resources.depth_stencil_view, &resources.depth_stencil_view,
); );
self.context.RSSetViewports(Some(&[resources.viewport])) self.context.RSSetViewports(Some(&[resources.viewport]))
@ -408,7 +457,7 @@ pub mod d3d11_hello_triangle {
unsafe { unsafe {
let color = [0.3, 0.4, 0.6, 1.0]; let color = [0.3, 0.4, 0.6, 1.0];
self.context self.context
.ClearRenderTargetView(&resources.backbuffer_rtv, color.as_ptr()); .ClearRenderTargetView(&resources.renderbufffer_rtv, color.as_ptr());
self.context.ClearDepthStencilView( self.context.ClearDepthStencilView(
&resources.depth_stencil_view, &resources.depth_stencil_view,
D3D11_CLEAR_DEPTH.0, D3D11_CLEAR_DEPTH.0,
@ -443,8 +492,11 @@ pub mod d3d11_hello_triangle {
unsafe { unsafe {
let mut tex2d_desc = Default::default(); let mut tex2d_desc = Default::default();
resources.backbuffer.GetDesc(&mut tex2d_desc); resources.renderbuffer.GetDesc(&mut tex2d_desc);
let mut backbuffer_copy = None; let mut backbuffer_desc = Default::default();
resources.backbuffer.as_ref().unwrap().GetDesc(&mut backbuffer_desc);
let mut renderbuffer_copy = None;
self.device.CreateTexture2D( self.device.CreateTexture2D(
&D3D11_TEXTURE2D_DESC { &D3D11_TEXTURE2D_DESC {
@ -453,11 +505,11 @@ pub mod d3d11_hello_triangle {
..tex2d_desc ..tex2d_desc
}, },
None, 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; let mut copy_srv = None;
self.device.CreateShaderResourceView( self.device.CreateShaderResourceView(
@ -494,6 +546,7 @@ pub mod d3d11_hello_triangle {
Some(&mut rtv), Some(&mut rtv),
)?; )?;
// eprintln!("w: {} h: {}", backbuffer_desc.Width, backbuffer_desc.Height);
self.filter self.filter
.frame( .frame(
D3D11InputView { D3D11InputView {
@ -508,10 +561,10 @@ pub mod d3d11_hello_triangle {
y: resources.viewport.TopLeftY, y: resources.viewport.TopLeftY,
output: D3D11OutputView { output: D3D11OutputView {
size: Size { size: Size {
width: tex2d_desc.Width, width: backbuffer_desc.Width,
height: tex2d_desc.Height, height: backbuffer_desc.Height,
}, },
handle: resources.backbuffer_rtv.clone(), handle: resources.backbuffer_rtv.as_ref().unwrap().clone(),
}, },
mvp: None, mvp: None,
}, },

View file

@ -34,7 +34,9 @@ mod tests {
fn triangle_d3d11() { fn triangle_d3d11() {
let sample = hello_triangle::d3d11_hello_triangle::Sample::new( let sample = hello_triangle::d3d11_hello_triangle::Sample::new(
"../test/slang-shaders/crt/crt-royale.slangp", "../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 { Some(&FilterChainOptionsD3D11 {
use_deferred_context: false, use_deferred_context: false,
force_no_mipmaps: false, force_no_mipmaps: false,

View file

@ -47,7 +47,7 @@ mod tests {
let filter = FilterChainVulkan::load_from_path( let filter = FilterChainVulkan::load_from_path(
&base, &base,
// "../test/slang-shaders/border/gameboy-player/gameboy-player-crt-royale.slangp", // "../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", // "../test/basic.slangp",
Some(&FilterChainOptionsVulkan { Some(&FilterChainOptionsVulkan {
frames_in_flight: 3, frames_in_flight: 3,

View file

@ -66,7 +66,7 @@ int main(int, char**)
auto libra = librashader_load_instance(); auto libra = librashader_load_instance();
libra_shader_preset_t preset; libra_shader_preset_t preset;
auto error = libra.preset_create( 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; libra_d3d11_filter_chain_t filter_chain;
filter_chain_d3d11_opt_t opt = { filter_chain_d3d11_opt_t opt = {