diff --git a/librashader-runtime-d3d12/src/error.rs b/librashader-runtime-d3d12/src/error.rs index 7139d07..29fb556 100644 --- a/librashader-runtime-d3d12/src/error.rs +++ b/librashader-runtime-d3d12/src/error.rs @@ -3,6 +3,7 @@ use d3d12_descriptor_heap::D3D12DescriptorHeapError; use thiserror::Error; +use windows::Win32::Graphics::Direct3D12::D3D12_RESOURCE_DIMENSION; /// Cumulative error type for Direct3D12 filter chains. #[derive(Error, Debug)] @@ -26,6 +27,8 @@ pub enum FilterChainError { HeapError(#[from] D3D12DescriptorHeapError), #[error("allocation error")] AllocationError(#[from] gpu_allocator::AllocationError), + #[error("invalid resource dimension {0:?}")] + InvalidDimensionError(D3D12_RESOURCE_DIMENSION), #[error("unreachable")] Infallible(#[from] std::convert::Infallible), } diff --git a/librashader-runtime-d3d12/src/filter_chain.rs b/librashader-runtime-d3d12/src/filter_chain.rs index 60c7705..91d19d1 100644 --- a/librashader-runtime-d3d12/src/filter_chain.rs +++ b/librashader-runtime-d3d12/src/filter_chain.rs @@ -68,7 +68,7 @@ pub struct FilterChainD3D12 { pub(crate) feedback_framebuffers: Box<[OwnedImage]>, pub(crate) history_framebuffers: VecDeque, staging_heap: D3D12DescriptorHeap, - rtv_heap: D3D12DescriptorHeap, + pub(crate) rtv_heap: D3D12DescriptorHeap, work_heap: ID3D12DescriptorHeap, sampler_heap: ID3D12DescriptorHeap, diff --git a/librashader-runtime-d3d12/src/framebuffer.rs b/librashader-runtime-d3d12/src/framebuffer.rs index f2fe905..70fc50f 100644 --- a/librashader-runtime-d3d12/src/framebuffer.rs +++ b/librashader-runtime-d3d12/src/framebuffer.rs @@ -16,20 +16,20 @@ use librashader_runtime::scaling::{MipmapSize, ScaleFramebuffer, ViewportSize}; use parking_lot::Mutex; use std::mem::ManuallyDrop; use std::sync::Arc; +use windows::core::Interface; use windows::Win32::Graphics::Direct3D12::{ ID3D12Device, ID3D12GraphicsCommandList, ID3D12Resource, D3D12_BOX, 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_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_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_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_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, }; use windows::Win32::Graphics::Dxgi::Common::{DXGI_FORMAT, DXGI_SAMPLE_DESC}; @@ -309,32 +309,7 @@ impl OwnedImage { &self, heap: &mut D3D12DescriptorHeap, ) -> error::Result { - let descriptor = heap.allocate_descriptor()?; - - 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(), - )) + D3D12OutputView::new_from_resource_internal(self.resource.to_ref(), &self.device, heap) } pub fn scale( diff --git a/librashader-runtime-d3d12/src/texture.rs b/librashader-runtime-d3d12/src/texture.rs index 610556e..6f42986 100644 --- a/librashader-runtime-d3d12/src/texture.rs +++ b/librashader-runtime-d3d12/src/texture.rs @@ -1,12 +1,22 @@ use crate::descriptor_heap::{CpuStagingHeap, RenderTargetHeap}; +use crate::{error, FilterChainD3D12}; use crate::resource::{OutlivesFrame, ResourceHandleStrategy}; use d3d12_descriptor_heap::{D3D12DescriptorHeap, D3D12DescriptorHeapSlot}; use librashader_common::{FilterMode, GetSize, Size, WrapMode}; use std::mem::ManuallyDrop; +use std::ops::Deref; 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; +/// 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. #[derive(Clone)] pub struct D3D12InputImage<'a> { @@ -87,6 +97,52 @@ impl D3D12OutputView { 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 { + 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, + ) -> error::Result { + 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 {