d3d12: implement history

This commit is contained in:
chyyran 2023-02-05 18:03:38 -05:00
parent 6a1138f0dc
commit 271788b9c6
7 changed files with 139 additions and 28 deletions

View file

@ -7,6 +7,7 @@ use crate::framebuffer::OwnedImage;
use crate::graphics_pipeline::{D3D12GraphicsPipeline, D3D12RootSignature}; use crate::graphics_pipeline::{D3D12GraphicsPipeline, D3D12RootSignature};
use crate::luts::LutTexture; use crate::luts::LutTexture;
use crate::mipmap::D3D12MipmapGen; use crate::mipmap::D3D12MipmapGen;
use crate::options::FilterChainOptionsD3D12;
use crate::quad_render::DrawQuad; use crate::quad_render::DrawQuad;
use crate::render_target::RenderTarget; use crate::render_target::RenderTarget;
use crate::samplers::SamplerSet; use crate::samplers::SamplerSet;
@ -41,12 +42,13 @@ use windows::Win32::Graphics::Direct3D::Dxc::{
use windows::Win32::Graphics::Direct3D12::{ use windows::Win32::Graphics::Direct3D12::{
ID3D12CommandAllocator, ID3D12CommandQueue, ID3D12DescriptorHeap, ID3D12Device, ID3D12Fence, ID3D12CommandAllocator, ID3D12CommandQueue, ID3D12DescriptorHeap, ID3D12Device, ID3D12Fence,
ID3D12GraphicsCommandList, D3D12_COMMAND_LIST_TYPE_DIRECT, D3D12_COMMAND_QUEUE_DESC, ID3D12GraphicsCommandList, D3D12_COMMAND_LIST_TYPE_DIRECT, D3D12_COMMAND_QUEUE_DESC,
D3D12_COMMAND_QUEUE_FLAG_NONE, D3D12_FENCE_FLAG_NONE, D3D12_COMMAND_QUEUE_FLAG_NONE, D3D12_FENCE_FLAG_NONE, D3D12_RESOURCE_STATE_COPY_DEST,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
D3D12_RESOURCE_STATE_RENDER_TARGET,
}; };
use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT_UNKNOWN;
use windows::Win32::System::Threading::{CreateEventA, ResetEvent, WaitForSingleObject}; use windows::Win32::System::Threading::{CreateEventA, ResetEvent, WaitForSingleObject};
use windows::Win32::System::WindowsProgramming::INFINITE; use windows::Win32::System::WindowsProgramming::INFINITE;
use crate::options::FilterChainOptionsD3D12;
type DxilShaderPassMeta = ShaderPassArtifact<impl CompileReflectShader<DXIL, GlslangCompilation>>; type DxilShaderPassMeta = ShaderPassArtifact<impl CompileReflectShader<DXIL, GlslangCompilation>>;
type HlslShaderPassMeta = ShaderPassArtifact<impl CompileReflectShader<HLSL, GlslangCompilation>>; type HlslShaderPassMeta = ShaderPassArtifact<impl CompileReflectShader<HLSL, GlslangCompilation>>;
@ -140,10 +142,15 @@ impl FilterChainD3D12 {
let root_signature = D3D12RootSignature::new(device)?; let root_signature = D3D12RootSignature::new(device)?;
let (texture_heap, sampler_heap, filters) = let (texture_heap, sampler_heap, filters) = FilterChainD3D12::init_passes(
FilterChainD3D12::init_passes(device, &root_signature, passes, hlsl_passes, &semantics, device,
options.map_or(false, |o| o.force_hlsl_pipeline)) &root_signature,
.unwrap(); passes,
hlsl_passes,
&semantics,
options.map_or(false, |o| o.force_hlsl_pipeline),
)
.unwrap();
// initialize output framebuffers // initialize output framebuffers
let mut output_framebuffers = Vec::new(); let mut output_framebuffers = Vec::new();
@ -359,8 +366,7 @@ impl FilterChainD3D12 {
for ( for (
index, index,
((((config, source, mut dxil), (_, _, mut hlsl)), ((((config, source, mut dxil), (_, _, mut hlsl)), mut texture_heap), mut sampler_heap),
mut texture_heap), mut sampler_heap),
) in passes ) in passes
.into_iter() .into_iter()
.zip(hlsl_passes) .zip(hlsl_passes)
@ -460,6 +466,31 @@ impl FilterChainD3D12 {
Ok((texture_heap_handle, sampler_heap_handle, filters)) Ok((texture_heap_handle, sampler_heap_handle, filters))
} }
fn push_history(
&mut self,
cmd: &ID3D12GraphicsCommandList,
input: &InputTexture,
) -> error::Result<()> {
if let Some(mut back) = self.history_framebuffers.pop_back() {
if back.size != input.size
|| (input.format != DXGI_FORMAT_UNKNOWN && input.format != back.format.into())
{
// eprintln!("[history] resizing");
// old back will get dropped.. do we need to defer?
let _old_back = std::mem::replace(
&mut back,
OwnedImage::new(&self.common.d3d12, input.size, input.format.into(), false)?,
);
}
unsafe {
back.copy_from(cmd, input)?;
}
self.history_framebuffers.push_front(back);
}
Ok(())
}
/// Process a frame with the input image. /// Process a frame with the input image.
pub fn frame( pub fn frame(
&mut self, &mut self,
@ -650,7 +681,8 @@ impl FilterChainD3D12 {
)?; )?;
} }
// todo: history self.push_history(&cmd, &original)?;
Ok(()) Ok(())
} }
} }

View file

@ -1,24 +1,27 @@
use crate::descriptor_heap::{CpuStagingHeap, D3D12DescriptorHeap, RenderTargetHeap}; use crate::descriptor_heap::{CpuStagingHeap, D3D12DescriptorHeap, RenderTargetHeap};
use crate::error;
use crate::error::assume_d3d12_init; use crate::error::assume_d3d12_init;
use crate::texture::{InputTexture, OutputTexture}; use crate::texture::{InputTexture, OutputTexture};
use crate::util::d3d12_get_closest_format; use crate::util::d3d12_get_closest_format;
use crate::{error, util};
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode}; use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
use librashader_presets::Scale2D; use librashader_presets::Scale2D;
use librashader_runtime::scaling::{MipmapSize, ViewportSize}; use librashader_runtime::scaling::{MipmapSize, ViewportSize};
use std::ops::Deref; use std::ops::Deref;
use windows::Win32::Graphics::Direct3D12::{ use windows::Win32::Graphics::Direct3D12::{
ID3D12Device, ID3D12Resource, D3D12_CPU_PAGE_PROPERTY_UNKNOWN, ID3D12Device, ID3D12GraphicsCommandList, ID3D12Resource, D3D12_BOX,
D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING, D3D12_FEATURE_DATA_FORMAT_SUPPORT, D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
D3D12_FORMAT_SUPPORT1_MIP, D3D12_FORMAT_SUPPORT1_RENDER_TARGET, D3D12_FEATURE_DATA_FORMAT_SUPPORT, D3D12_FORMAT_SUPPORT1_MIP,
D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE, D3D12_FORMAT_SUPPORT1_TEXTURE2D, D3D12_FORMAT_SUPPORT1_RENDER_TARGET, D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE,
D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE, D3D12_HEAP_FLAG_NONE, D3D12_HEAP_PROPERTIES, D3D12_FORMAT_SUPPORT1_TEXTURE2D, D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE, D3D12_HEAP_FLAG_NONE,
D3D12_HEAP_TYPE_DEFAULT, D3D12_MEMORY_POOL_UNKNOWN, D3D12_RENDER_TARGET_VIEW_DESC, D3D12_HEAP_PROPERTIES, D3D12_HEAP_TYPE_DEFAULT, D3D12_MEMORY_POOL_UNKNOWN,
D3D12_RENDER_TARGET_VIEW_DESC_0, D3D12_RESOURCE_DESC, D3D12_RESOURCE_DIMENSION_TEXTURE2D, D3D12_RENDER_TARGET_VIEW_DESC, D3D12_RENDER_TARGET_VIEW_DESC_0, D3D12_RESOURCE_DESC,
D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, D3D12_RESOURCE_DIMENSION_TEXTURE2D, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RTV_DIMENSION_TEXTURE2D, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_DEST,
D3D12_SHADER_RESOURCE_VIEW_DESC, D3D12_SHADER_RESOURCE_VIEW_DESC_0, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
D3D12_SRV_DIMENSION_TEXTURE2D, D3D12_TEX2D_RTV, D3D12_TEX2D_SRV, D3D12_RTV_DIMENSION_TEXTURE2D, D3D12_SHADER_RESOURCE_VIEW_DESC,
D3D12_SHADER_RESOURCE_VIEW_DESC_0, D3D12_SRV_DIMENSION_TEXTURE2D, D3D12_TEX2D_RTV,
D3D12_TEX2D_SRV, D3D12_TEXTURE_COPY_LOCATION, D3D12_TEXTURE_COPY_LOCATION_0,
D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
}; };
use windows::Win32::Graphics::Dxgi::Common::DXGI_SAMPLE_DESC; use windows::Win32::Graphics::Dxgi::Common::DXGI_SAMPLE_DESC;
@ -26,7 +29,7 @@ use windows::Win32::Graphics::Dxgi::Common::DXGI_SAMPLE_DESC;
pub(crate) struct OwnedImage { pub(crate) struct OwnedImage {
pub(crate) handle: ID3D12Resource, pub(crate) handle: ID3D12Resource,
pub(crate) size: Size<u32>, pub(crate) size: Size<u32>,
format: ImageFormat, pub(crate) format: ImageFormat,
device: ID3D12Device, device: ID3D12Device,
max_mipmap: u16, max_mipmap: u16,
} }
@ -103,6 +106,72 @@ impl OwnedImage {
} }
} }
/// SAFETY: self must fit the source image
/// source must be in D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE
pub unsafe fn copy_from(
&self,
cmd: &ID3D12GraphicsCommandList,
input: &InputTexture,
) -> error::Result<()> {
util::d3d12_resource_transition(
cmd,
&input.resource,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
D3D12_RESOURCE_STATE_COPY_SOURCE,
);
util::d3d12_resource_transition(
cmd,
&self.handle,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
D3D12_RESOURCE_STATE_COPY_DEST,
);
unsafe {
cmd.CopyTextureRegion(
&D3D12_TEXTURE_COPY_LOCATION {
pResource: windows::core::ManuallyDrop::new(&self.handle),
Type: D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
Anonymous: D3D12_TEXTURE_COPY_LOCATION_0 {
SubresourceIndex: 0,
},
},
0,
0,
0,
&D3D12_TEXTURE_COPY_LOCATION {
pResource: windows::core::ManuallyDrop::new(&input.resource),
Type: D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
Anonymous: D3D12_TEXTURE_COPY_LOCATION_0 {
SubresourceIndex: 0,
},
},
Some(&D3D12_BOX {
left: 0,
top: 0,
front: 0,
right: input.size.width,
bottom: input.size.height,
back: 1,
}),
);
}
util::d3d12_resource_transition(
cmd,
&input.resource,
D3D12_RESOURCE_STATE_COPY_SOURCE,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
);
util::d3d12_resource_transition(
cmd,
&self.handle,
D3D12_RESOURCE_STATE_COPY_DEST,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
);
Ok(())
}
pub(crate) fn create_shader_resource_view( pub(crate) fn create_shader_resource_view(
&self, &self,
heap: &mut D3D12DescriptorHeap<CpuStagingHeap>, heap: &mut D3D12DescriptorHeap<CpuStagingHeap>,
@ -132,6 +201,7 @@ impl OwnedImage {
} }
Ok(InputTexture::new( Ok(InputTexture::new(
self.handle.clone(),
descriptor, descriptor,
self.size, self.size,
self.format, self.format,

View file

@ -618,6 +618,7 @@ pub mod d3d12_hello_triangle {
.frame( .frame(
command_list, command_list,
InputTexture::new_from_raw( InputTexture::new_from_raw(
resources.framebuffer.clone(),
framebuffer, framebuffer,
Size::new( Size::new(
resources.viewport.Width as u32, resources.viewport.Width as u32,

View file

@ -11,12 +11,12 @@ mod graphics_pipeline;
mod hello_triangle; mod hello_triangle;
mod luts; mod luts;
mod mipmap; mod mipmap;
mod options;
mod quad_render; mod quad_render;
mod render_target; mod render_target;
mod samplers; mod samplers;
mod texture; mod texture;
mod util; mod util;
mod options;
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
@ -28,8 +28,8 @@ mod tests {
let sample = hello_triangle::d3d12_hello_triangle::Sample::new( let sample = hello_triangle::d3d12_hello_triangle::Sample::new(
// "../test/slang-shaders/crt/crt-lottes.slangp", // "../test/slang-shaders/crt/crt-lottes.slangp",
// "../test/slang-shaders/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp", // "../test/slang-shaders/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp",
"../test/slang-shaders/crt/crt-royale.slangp", // "../test/slang-shaders/crt/crt-royale.slangp",
"../test/slang-shaders/vhs/VHSPro.slangp",
&SampleCommandLine { &SampleCommandLine {
use_warp_device: false, use_warp_device: false,
}, },

View file

@ -183,6 +183,7 @@ impl LutTexture {
} }
let view = InputTexture::new( let view = InputTexture::new(
resource.clone(),
descriptor, descriptor,
source.size, source.size,
ImageFormat::R8G8B8A8Unorm, ImageFormat::R8G8B8A8Unorm,

View file

@ -1,7 +1,7 @@
use crate::descriptor_heap::{CpuStagingHeap, D3D12DescriptorHeapSlot, RenderTargetHeap}; use crate::descriptor_heap::{CpuStagingHeap, D3D12DescriptorHeapSlot, RenderTargetHeap};
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode}; use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
use std::ops::Deref; use std::ops::Deref;
use windows::Win32::Graphics::Direct3D12::D3D12_CPU_DESCRIPTOR_HANDLE; use windows::Win32::Graphics::Direct3D12::{ID3D12Resource, D3D12_CPU_DESCRIPTOR_HANDLE};
use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT; use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT;
#[derive(Clone)] #[derive(Clone)]
@ -61,15 +61,17 @@ impl OutputTexture {
#[derive(Clone)] #[derive(Clone)]
pub struct InputTexture { pub struct InputTexture {
pub(crate) resource: ID3D12Resource,
pub(crate) descriptor: InputDescriptor, pub(crate) descriptor: InputDescriptor,
pub(crate) size: Size<u32>, pub(crate) size: Size<u32>,
format: DXGI_FORMAT, pub(crate) format: DXGI_FORMAT,
pub(crate) wrap_mode: WrapMode, pub(crate) wrap_mode: WrapMode,
pub(crate) filter: FilterMode, pub(crate) filter: FilterMode,
} }
impl InputTexture { impl InputTexture {
pub fn new( pub fn new(
resource: ID3D12Resource,
handle: D3D12DescriptorHeapSlot<CpuStagingHeap>, handle: D3D12DescriptorHeapSlot<CpuStagingHeap>,
size: Size<u32>, size: Size<u32>,
format: ImageFormat, format: ImageFormat,
@ -78,6 +80,7 @@ impl InputTexture {
) -> InputTexture { ) -> InputTexture {
let srv = InputDescriptor::Owned(handle); let srv = InputDescriptor::Owned(handle);
InputTexture { InputTexture {
resource,
descriptor: srv, descriptor: srv,
size, size,
format: format.into(), format: format.into(),
@ -88,6 +91,7 @@ impl InputTexture {
// unsafe since the lifetime of the handle has to survive // unsafe since the lifetime of the handle has to survive
pub unsafe fn new_from_raw( pub unsafe fn new_from_raw(
resource: ID3D12Resource,
handle: D3D12_CPU_DESCRIPTOR_HANDLE, handle: D3D12_CPU_DESCRIPTOR_HANDLE,
size: Size<u32>, size: Size<u32>,
format: DXGI_FORMAT, format: DXGI_FORMAT,
@ -96,6 +100,7 @@ impl InputTexture {
) -> InputTexture { ) -> InputTexture {
let srv = InputDescriptor::Raw(handle); let srv = InputDescriptor::Raw(handle);
InputTexture { InputTexture {
resource,
descriptor: srv, descriptor: srv,
size, size,
format, format,

View file

@ -25,4 +25,6 @@ pub mod ringbuffer;
/// Generic implementation of semantics binding. /// Generic implementation of semantics binding.
pub mod binding; pub mod binding;
/// VBO helper utilities
pub mod quad; pub mod quad;