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,
Size::new(1, 1),
ImageFormat::R8G8B8A8Unorm,
false
)
});
@ -139,6 +140,7 @@ impl FilterChainD3D11 {
&current_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
)?;
}

View file

@ -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 {

View file

@ -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<u32>,
pub format: DXGI_FORMAT,
render: ID3D11Texture2D,
pub(crate) size: Size<u32>,
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<u32>,
format: ImageFormat,
mipmap: bool,
) -> error::Result<OwnedFramebuffer> {
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<u32>,
_original: &InputTexture,
source: &InputTexture,
should_mipmap: bool,
) -> error::Result<Size<u32>> {
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,

View file

@ -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<S>(mut sample: S) -> Result<()>
@ -168,6 +178,10 @@ fn sample_wndproc<S: DXSample>(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<S: DXSample>(
unsafe { PostQuitMessage(0) };
LRESULT::default()
}
_ => {
let user_data = unsafe { GetWindowLongPtrA(window, GWLP_USERDATA) };
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::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<ID3D11Texture2D>,
pub backbuffer_rtv: Option<ID3D11RenderTargetView>,
pub viewport: D3D11_VIEWPORT,
pub shader_output: Option<ID3D11Texture2D>,
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,
},

View file

@ -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,

View file

@ -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,

View file

@ -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 = {