rt(d3d12): use InterfaceRef for D3D12InputImage to avoid refcount for input image

This commit is contained in:
chyyran 2024-09-29 00:30:39 -04:00 committed by Ronny Chan
parent b123f63a6e
commit 3c20c83bc9
6 changed files with 35 additions and 70 deletions

View file

@ -8,6 +8,7 @@ use std::ffi::CStr;
use std::mem::{ManuallyDrop, MaybeUninit}; use std::mem::{ManuallyDrop, MaybeUninit};
use std::ptr::NonNull; use std::ptr::NonNull;
use std::slice; use std::slice;
use windows::core::Interface;
use windows::Win32::Graphics::Direct3D12::{ use windows::Win32::Graphics::Direct3D12::{
ID3D12Device, ID3D12GraphicsCommandList, ID3D12Resource, D3D12_CPU_DESCRIPTOR_HANDLE, ID3D12Device, ID3D12GraphicsCommandList, ID3D12Resource, D3D12_CPU_DESCRIPTOR_HANDLE,
}; };
@ -93,19 +94,6 @@ config_struct! {
} }
} }
impl TryFrom<libra_source_image_d3d12_t> for D3D12InputImage {
type Error = LibrashaderError;
fn try_from(value: libra_source_image_d3d12_t) -> Result<Self, Self::Error> {
let resource = value.resource.clone();
Ok(D3D12InputImage {
resource: ManuallyDrop::into_inner(resource),
descriptor: value.descriptor,
})
}
}
extern_fn! { extern_fn! {
/// Create the filter chain given the shader preset. /// Create the filter chain given the shader preset.
/// ///
@ -295,7 +283,10 @@ extern_fn! {
} }
}; };
let image = image.try_into()?; let image = D3D12InputImage {
resource: image.resource.to_ref(),
descriptor: image.descriptor,
};
unsafe { unsafe {
chain.frame(&command_list, image, &viewport, frame_count, options.as_ref())?; chain.frame(&command_list, image, &viewport, frame_count, options.as_ref())?;
} }

View file

@ -45,7 +45,7 @@ pub struct Direct3D12 {
_cpu_heap: D3D12DescriptorHeap<CpuStagingHeap>, _cpu_heap: D3D12DescriptorHeap<CpuStagingHeap>,
rtv_heap: D3D12DescriptorHeap<RenderTargetHeap>, rtv_heap: D3D12DescriptorHeap<RenderTargetHeap>,
texture: D3D12InputImage, texture: ID3D12Resource,
_heap_slot: D3D12DescriptorHeapSlot<CpuStagingHeap>, _heap_slot: D3D12DescriptorHeapSlot<CpuStagingHeap>,
command_pool: ID3D12CommandAllocator, command_pool: ID3D12CommandAllocator,
queue: ID3D12CommandQueue, queue: ID3D12CommandQueue,
@ -154,7 +154,10 @@ impl RenderTest for Direct3D12 {
for frame in 0..=frame_count { for frame in 0..=frame_count {
filter_chain.frame( filter_chain.frame(
&cmd, &cmd,
self.texture.clone(), D3D12InputImage {
resource: self.texture.to_ref(),
descriptor: *self._heap_slot.as_ref(),
},
&viewport, &viewport,
frame, frame,
options.as_ref(), options.as_ref(),
@ -249,7 +252,7 @@ impl Direct3D12 {
path: &Path, path: &Path,
) -> anyhow::Result<( ) -> anyhow::Result<(
Image<BGRA8>, Image<BGRA8>,
D3D12InputImage, ID3D12Resource,
D3D12DescriptorHeapSlot<CpuStagingHeap>, D3D12DescriptorHeapSlot<CpuStagingHeap>,
)> { )> {
// 1 time queue infrastructure for lut uploads // 1 time queue infrastructure for lut uploads
@ -392,14 +395,7 @@ impl Direct3D12 {
CloseHandle(fence_event)?; CloseHandle(fence_event)?;
} }
Ok(( Ok((image, resource, descriptor))
image,
D3D12InputImage {
resource,
descriptor: descriptor.as_ref().clone(),
},
descriptor,
))
} }
} }

View file

@ -295,7 +295,7 @@ impl OwnedImage {
); );
} }
Ok(InputTexture::new::<OutlivesFrame, _>( Ok(InputTexture::new(
&self.resource, &self.resource,
descriptor, descriptor,
self.size, self.size,

View file

@ -201,7 +201,7 @@ impl LutTexture {
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
); );
let view = InputTexture::new::<OutlivesFrame, _>( let view = InputTexture::new(
&resource, &resource,
descriptor, descriptor,
source.size, source.size,

View file

@ -1,15 +1,16 @@
use crate::descriptor_heap::{CpuStagingHeap, RenderTargetHeap}; use crate::descriptor_heap::{CpuStagingHeap, RenderTargetHeap};
use crate::resource::ResourceHandleStrategy; use crate::resource::{OutlivesFrame, ResourceHandleStrategy};
use d3d12_descriptor_heap::D3D12DescriptorHeapSlot; use d3d12_descriptor_heap::{D3D12DescriptorHeap, D3D12DescriptorHeapSlot};
use librashader_common::{FilterMode, GetSize, Size, WrapMode}; use librashader_common::{FilterMode, GetSize, Size, WrapMode};
use std::mem::ManuallyDrop; use std::mem::ManuallyDrop;
use windows::core::InterfaceRef;
use windows::Win32::Graphics::Direct3D12::{ID3D12Resource, 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;
/// An image for use as shader resource view. /// An image for use as shader resource view.
#[derive(Clone)] #[derive(Clone)]
pub struct D3D12InputImage { pub struct D3D12InputImage<'a> {
pub resource: ID3D12Resource, pub resource: InterfaceRef<'a, ID3D12Resource>,
pub descriptor: D3D12_CPU_DESCRIPTOR_HANDLE, pub descriptor: D3D12_CPU_DESCRIPTOR_HANDLE,
} }
@ -95,12 +96,13 @@ pub struct InputTexture {
pub(crate) 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,
drop_flag: bool,
} }
impl InputTexture { impl InputTexture {
pub fn new<S: ResourceHandleStrategy<T>, T>( // Create a new input texture, with runtime lifetime tracking.
resource: &T, // The source owned framebuffer must outlive this input.
pub fn new(
resource: &ManuallyDrop<ID3D12Resource>,
handle: D3D12DescriptorHeapSlot<CpuStagingHeap>, handle: D3D12DescriptorHeapSlot<CpuStagingHeap>,
size: Size<u32>, size: Size<u32>,
format: DXGI_FORMAT, format: DXGI_FORMAT,
@ -114,13 +116,12 @@ impl InputTexture {
// as valid for the lifetime of handle. // as valid for the lifetime of handle.
// Also, resource is non-null by construction. // Also, resource is non-null by construction.
// Option<T> and <T> have the same layout. // Option<T> and <T> have the same layout.
resource: unsafe { std::mem::transmute(S::obtain(resource)) }, resource: unsafe { std::mem::transmute(OutlivesFrame::obtain(resource)) },
descriptor: srv, descriptor: srv,
size, size,
format, format,
wrap_mode, wrap_mode,
filter, filter,
drop_flag: S::NEEDS_CLEANUP,
} }
} }
@ -132,42 +133,27 @@ impl InputTexture {
) -> InputTexture { ) -> InputTexture {
let desc = unsafe { image.resource.GetDesc() }; let desc = unsafe { image.resource.GetDesc() };
InputTexture { InputTexture {
resource: ManuallyDrop::new(image.resource.clone()), resource: unsafe { std::mem::transmute(image.resource) },
descriptor: InputDescriptor::Raw(image.descriptor), descriptor: InputDescriptor::Raw(image.descriptor),
size: Size::new(desc.Width as u32, desc.Height), size: Size::new(desc.Width as u32, desc.Height),
format: desc.Format, format: desc.Format,
wrap_mode, wrap_mode,
filter, filter,
drop_flag: true,
} }
} }
} }
impl Clone for InputTexture { impl Clone for InputTexture {
fn clone(&self) -> Self { fn clone(&self) -> Self {
// ensure lifetime for raw resources or if there is a drop flag // SAFETY: the parent doesn't have drop flag, so that means
if self.descriptor.is_raw() || self.drop_flag { // we don't need to handle drop.
InputTexture { InputTexture {
resource: ManuallyDrop::clone(&self.resource), resource: unsafe { std::mem::transmute_copy(&self.resource) },
descriptor: self.descriptor.clone(), descriptor: self.descriptor.clone(),
size: self.size, size: self.size,
format: self.format, format: self.format,
wrap_mode: self.wrap_mode, wrap_mode: self.wrap_mode,
filter: self.filter, filter: self.filter,
drop_flag: true,
}
} else {
// SAFETY: the parent doesn't have drop flag, so that means
// we don't need to handle drop.
InputTexture {
resource: unsafe { std::mem::transmute_copy(&self.resource) },
descriptor: self.descriptor.clone(),
size: self.size,
format: self.format,
wrap_mode: self.wrap_mode,
filter: self.filter,
drop_flag: false,
}
} }
} }
} }
@ -185,11 +171,3 @@ impl GetSize<u32> for D3D12OutputView {
Ok(self.size) Ok(self.size)
} }
} }
impl Drop for InputTexture {
fn drop(&mut self) {
if self.drop_flag {
unsafe { ManuallyDrop::drop(&mut self.resource) }
}
}
}

View file

@ -620,7 +620,7 @@ pub mod d3d12_hello_triangle {
.frame( .frame(
command_list, command_list,
D3D12InputImage { D3D12InputImage {
resource: ID3D12Resource::clone(&*resources.framebuffer), resource: resources.framebuffer.to_ref(),
descriptor: framebuffer, descriptor: framebuffer,
}, },
&Viewport { &Viewport {