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::luts::LutTexture;
use crate::mipmap::D3D12MipmapGen;
use crate::options::FilterChainOptionsD3D12;
use crate::quad_render::DrawQuad;
use crate::render_target::RenderTarget;
use crate::samplers::SamplerSet;
@ -41,12 +42,13 @@ use windows::Win32::Graphics::Direct3D::Dxc::{
use windows::Win32::Graphics::Direct3D12::{
ID3D12CommandAllocator, ID3D12CommandQueue, ID3D12DescriptorHeap, ID3D12Device, ID3D12Fence,
ID3D12GraphicsCommandList, D3D12_COMMAND_LIST_TYPE_DIRECT, D3D12_COMMAND_QUEUE_DESC,
D3D12_COMMAND_QUEUE_FLAG_NONE, D3D12_FENCE_FLAG_NONE,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET,
D3D12_COMMAND_QUEUE_FLAG_NONE, D3D12_FENCE_FLAG_NONE, D3D12_RESOURCE_STATE_COPY_DEST,
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::WindowsProgramming::INFINITE;
use crate::options::FilterChainOptionsD3D12;
type DxilShaderPassMeta = ShaderPassArtifact<impl CompileReflectShader<DXIL, GlslangCompilation>>;
type HlslShaderPassMeta = ShaderPassArtifact<impl CompileReflectShader<HLSL, GlslangCompilation>>;
@ -140,10 +142,15 @@ impl FilterChainD3D12 {
let root_signature = D3D12RootSignature::new(device)?;
let (texture_heap, sampler_heap, filters) =
FilterChainD3D12::init_passes(device, &root_signature, passes, hlsl_passes, &semantics,
options.map_or(false, |o| o.force_hlsl_pipeline))
.unwrap();
let (texture_heap, sampler_heap, filters) = FilterChainD3D12::init_passes(
device,
&root_signature,
passes,
hlsl_passes,
&semantics,
options.map_or(false, |o| o.force_hlsl_pipeline),
)
.unwrap();
// initialize output framebuffers
let mut output_framebuffers = Vec::new();
@ -359,8 +366,7 @@ impl FilterChainD3D12 {
for (
index,
((((config, source, mut dxil), (_, _, mut hlsl)),
mut texture_heap), mut sampler_heap),
((((config, source, mut dxil), (_, _, mut hlsl)), mut texture_heap), mut sampler_heap),
) in passes
.into_iter()
.zip(hlsl_passes)
@ -460,6 +466,31 @@ impl FilterChainD3D12 {
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.
pub fn frame(
&mut self,
@ -650,7 +681,8 @@ impl FilterChainD3D12 {
)?;
}
// todo: history
self.push_history(&cmd, &original)?;
Ok(())
}
}

View file

@ -1,24 +1,27 @@
use crate::descriptor_heap::{CpuStagingHeap, D3D12DescriptorHeap, RenderTargetHeap};
use crate::error;
use crate::error::assume_d3d12_init;
use crate::texture::{InputTexture, OutputTexture};
use crate::util::d3d12_get_closest_format;
use crate::{error, util};
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
use librashader_presets::Scale2D;
use librashader_runtime::scaling::{MipmapSize, ViewportSize};
use std::ops::Deref;
use windows::Win32::Graphics::Direct3D12::{
ID3D12Device, ID3D12Resource, D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING, D3D12_FEATURE_DATA_FORMAT_SUPPORT,
D3D12_FORMAT_SUPPORT1_MIP, D3D12_FORMAT_SUPPORT1_RENDER_TARGET,
D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE, D3D12_FORMAT_SUPPORT1_TEXTURE2D,
D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE, D3D12_HEAP_FLAG_NONE, D3D12_HEAP_PROPERTIES,
D3D12_HEAP_TYPE_DEFAULT, D3D12_MEMORY_POOL_UNKNOWN, D3D12_RENDER_TARGET_VIEW_DESC,
D3D12_RENDER_TARGET_VIEW_DESC_0, D3D12_RESOURCE_DESC, D3D12_RESOURCE_DIMENSION_TEXTURE2D,
D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, 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,
ID3D12Device, ID3D12GraphicsCommandList, ID3D12Resource, D3D12_BOX,
D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
D3D12_FEATURE_DATA_FORMAT_SUPPORT, D3D12_FORMAT_SUPPORT1_MIP,
D3D12_FORMAT_SUPPORT1_RENDER_TARGET, D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE,
D3D12_FORMAT_SUPPORT1_TEXTURE2D, D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE, D3D12_HEAP_FLAG_NONE,
D3D12_HEAP_PROPERTIES, D3D12_HEAP_TYPE_DEFAULT, D3D12_MEMORY_POOL_UNKNOWN,
D3D12_RENDER_TARGET_VIEW_DESC, D3D12_RENDER_TARGET_VIEW_DESC_0, D3D12_RESOURCE_DESC,
D3D12_RESOURCE_DIMENSION_TEXTURE2D, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET,
D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_DEST,
D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
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;
@ -26,7 +29,7 @@ use windows::Win32::Graphics::Dxgi::Common::DXGI_SAMPLE_DESC;
pub(crate) struct OwnedImage {
pub(crate) handle: ID3D12Resource,
pub(crate) size: Size<u32>,
format: ImageFormat,
pub(crate) format: ImageFormat,
device: ID3D12Device,
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(
&self,
heap: &mut D3D12DescriptorHeap<CpuStagingHeap>,
@ -132,6 +201,7 @@ impl OwnedImage {
}
Ok(InputTexture::new(
self.handle.clone(),
descriptor,
self.size,
self.format,

View file

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

View file

@ -11,12 +11,12 @@ mod graphics_pipeline;
mod hello_triangle;
mod luts;
mod mipmap;
mod options;
mod quad_render;
mod render_target;
mod samplers;
mod texture;
mod util;
mod options;
#[cfg(test)]
mod tests {
@ -28,8 +28,8 @@ mod tests {
let sample = hello_triangle::d3d12_hello_triangle::Sample::new(
// "../test/slang-shaders/crt/crt-lottes.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 {
use_warp_device: false,
},

View file

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

View file

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

View file

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