rt(d3d12): allow creating output view from a resource ref

This commit is contained in:
chyyran 2024-09-29 01:31:21 -04:00 committed by Ronny Chan
parent 3c20c83bc9
commit 40691cc406
4 changed files with 65 additions and 31 deletions

View file

@ -3,6 +3,7 @@
use d3d12_descriptor_heap::D3D12DescriptorHeapError; use d3d12_descriptor_heap::D3D12DescriptorHeapError;
use thiserror::Error; use thiserror::Error;
use windows::Win32::Graphics::Direct3D12::D3D12_RESOURCE_DIMENSION;
/// Cumulative error type for Direct3D12 filter chains. /// Cumulative error type for Direct3D12 filter chains.
#[derive(Error, Debug)] #[derive(Error, Debug)]
@ -26,6 +27,8 @@ pub enum FilterChainError {
HeapError(#[from] D3D12DescriptorHeapError), HeapError(#[from] D3D12DescriptorHeapError),
#[error("allocation error")] #[error("allocation error")]
AllocationError(#[from] gpu_allocator::AllocationError), AllocationError(#[from] gpu_allocator::AllocationError),
#[error("invalid resource dimension {0:?}")]
InvalidDimensionError(D3D12_RESOURCE_DIMENSION),
#[error("unreachable")] #[error("unreachable")]
Infallible(#[from] std::convert::Infallible), Infallible(#[from] std::convert::Infallible),
} }

View file

@ -68,7 +68,7 @@ pub struct FilterChainD3D12 {
pub(crate) feedback_framebuffers: Box<[OwnedImage]>, pub(crate) feedback_framebuffers: Box<[OwnedImage]>,
pub(crate) history_framebuffers: VecDeque<OwnedImage>, pub(crate) history_framebuffers: VecDeque<OwnedImage>,
staging_heap: D3D12DescriptorHeap<CpuStagingHeap>, staging_heap: D3D12DescriptorHeap<CpuStagingHeap>,
rtv_heap: D3D12DescriptorHeap<RenderTargetHeap>, pub(crate) rtv_heap: D3D12DescriptorHeap<RenderTargetHeap>,
work_heap: ID3D12DescriptorHeap, work_heap: ID3D12DescriptorHeap,
sampler_heap: ID3D12DescriptorHeap, sampler_heap: ID3D12DescriptorHeap,

View file

@ -16,20 +16,20 @@ use librashader_runtime::scaling::{MipmapSize, ScaleFramebuffer, ViewportSize};
use parking_lot::Mutex; use parking_lot::Mutex;
use std::mem::ManuallyDrop; use std::mem::ManuallyDrop;
use std::sync::Arc; use std::sync::Arc;
use windows::core::Interface;
use windows::Win32::Graphics::Direct3D12::{ use windows::Win32::Graphics::Direct3D12::{
ID3D12Device, ID3D12GraphicsCommandList, ID3D12Resource, D3D12_BOX, ID3D12Device, ID3D12GraphicsCommandList, ID3D12Resource, D3D12_BOX,
D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING, D3D12_FEATURE_DATA_FORMAT_SUPPORT, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING, D3D12_FEATURE_DATA_FORMAT_SUPPORT,
D3D12_FORMAT_SUPPORT1_MIP, D3D12_FORMAT_SUPPORT1_RENDER_TARGET, D3D12_FORMAT_SUPPORT1_MIP, D3D12_FORMAT_SUPPORT1_RENDER_TARGET,
D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE, D3D12_FORMAT_SUPPORT1_TEXTURE2D, D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE, D3D12_FORMAT_SUPPORT1_TEXTURE2D,
D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD, D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE, D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD, D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE,
D3D12_RENDER_TARGET_VIEW_DESC, D3D12_RENDER_TARGET_VIEW_DESC_0,
D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, D3D12_RESOURCE_DESC, D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, D3D12_RESOURCE_DESC,
D3D12_RESOURCE_DIMENSION_TEXTURE2D, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, D3D12_RESOURCE_DIMENSION_TEXTURE2D, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET,
D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_DEST,
D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RTV_DIMENSION_TEXTURE2D, D3D12_RESOURCE_STATE_RENDER_TARGET,
D3D12_SHADER_RESOURCE_VIEW_DESC, D3D12_SHADER_RESOURCE_VIEW_DESC_0, 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_SRV_DIMENSION_TEXTURE2D, D3D12_TEX2D_SRV, D3D12_TEXTURE_COPY_LOCATION,
D3D12_TEXTURE_COPY_LOCATION_0, D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, D3D12_TEXTURE_COPY_LOCATION_0, D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
}; };
use windows::Win32::Graphics::Dxgi::Common::{DXGI_FORMAT, DXGI_SAMPLE_DESC}; use windows::Win32::Graphics::Dxgi::Common::{DXGI_FORMAT, DXGI_SAMPLE_DESC};
@ -309,32 +309,7 @@ impl OwnedImage {
&self, &self,
heap: &mut D3D12DescriptorHeap<RenderTargetHeap>, heap: &mut D3D12DescriptorHeap<RenderTargetHeap>,
) -> error::Result<D3D12OutputView> { ) -> error::Result<D3D12OutputView> {
let descriptor = heap.allocate_descriptor()?; D3D12OutputView::new_from_resource_internal(self.resource.to_ref(), &self.device, heap)
unsafe {
let rtv_desc = D3D12_RENDER_TARGET_VIEW_DESC {
Format: self.format.into(),
ViewDimension: D3D12_RTV_DIMENSION_TEXTURE2D,
Anonymous: D3D12_RENDER_TARGET_VIEW_DESC_0 {
Texture2D: D3D12_TEX2D_RTV {
MipSlice: 0,
..Default::default()
},
},
};
self.device.CreateRenderTargetView(
self.handle.resource(),
Some(&rtv_desc),
*descriptor.as_ref(),
);
}
Ok(D3D12OutputView::new(
descriptor,
self.size,
self.format.into(),
))
} }
pub fn scale( pub fn scale(

View file

@ -1,12 +1,22 @@
use crate::descriptor_heap::{CpuStagingHeap, RenderTargetHeap}; use crate::descriptor_heap::{CpuStagingHeap, RenderTargetHeap};
use crate::{error, FilterChainD3D12};
use crate::resource::{OutlivesFrame, ResourceHandleStrategy}; use crate::resource::{OutlivesFrame, ResourceHandleStrategy};
use d3d12_descriptor_heap::{D3D12DescriptorHeap, 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 std::ops::Deref;
use windows::core::InterfaceRef; use windows::core::InterfaceRef;
use windows::Win32::Graphics::Direct3D12::{ID3D12Resource, D3D12_CPU_DESCRIPTOR_HANDLE}; use windows::Win32::Graphics::Direct3D12::{
ID3D12Device, ID3D12Resource, D3D12_CPU_DESCRIPTOR_HANDLE, D3D12_RENDER_TARGET_VIEW_DESC,
D3D12_RENDER_TARGET_VIEW_DESC_0, D3D12_RESOURCE_DIMENSION_TEXTURE2D,
D3D12_RTV_DIMENSION_TEXTURE2D, D3D12_TEX2D_RTV,
};
use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT; use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT;
/// A **non-owning** reference to a ID3D12Resource.
/// This does not `AddRef` or `Release` the underlying interface.
pub type D3D12ResourceRef<'a> = InterfaceRef<'a, ID3D12Resource>;
/// An image for use as shader resource view. /// An image for use as shader resource view.
#[derive(Clone)] #[derive(Clone)]
pub struct D3D12InputImage<'a> { pub struct D3D12InputImage<'a> {
@ -87,6 +97,52 @@ impl D3D12OutputView {
format, format,
} }
} }
/// Create a new output view from a resource ref, linked to the chain.
///
/// The output view will be automatically disposed on drop.
pub fn new_from_resource(
image: D3D12ResourceRef,
chain: &mut FilterChainD3D12
) -> error::Result<D3D12OutputView> {
Self::new_from_resource_internal(image, &chain.common.d3d12, &mut chain.rtv_heap)
}
/// Create a new output view from a resource ref
pub(crate) fn new_from_resource_internal(
image: D3D12ResourceRef,
device: &ID3D12Device,
heap: &mut D3D12DescriptorHeap<RenderTargetHeap>,
) -> error::Result<D3D12OutputView> {
let desc = unsafe { image.GetDesc() };
if desc.Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE2D {
return Err(crate::error::FilterChainError::InvalidDimensionError(
desc.Dimension,
));
}
let slot = heap.allocate_descriptor()?;
unsafe {
let rtv_desc = D3D12_RENDER_TARGET_VIEW_DESC {
Format: desc.Format,
ViewDimension: D3D12_RTV_DIMENSION_TEXTURE2D,
Anonymous: D3D12_RENDER_TARGET_VIEW_DESC_0 {
Texture2D: D3D12_TEX2D_RTV {
MipSlice: 0,
..Default::default()
},
},
};
device.CreateRenderTargetView(image.deref(), Some(&rtv_desc), *slot.as_ref());
}
Ok(Self::new(
slot,
Size::new(desc.Width as u32, desc.Height),
desc.Format,
))
}
} }
pub struct InputTexture { pub struct InputTexture {