rt(d3d12): allow construction of D3D12InputImage without a descriptor handle
This commit is contained in:
parent
c526b7043a
commit
0cb3880d7f
|
@ -283,9 +283,9 @@ extern_fn! {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let image = D3D12InputImage {
|
let image = D3D12InputImage::External {
|
||||||
resource: image.resource.to_ref(),
|
resource: image.resource.to_ref(),
|
||||||
descriptor: Some(image.descriptor),
|
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())?;
|
||||||
|
|
|
@ -154,10 +154,7 @@ impl RenderTest for Direct3D12 {
|
||||||
for frame in 0..=frame_count {
|
for frame in 0..=frame_count {
|
||||||
filter_chain.frame(
|
filter_chain.frame(
|
||||||
&cmd,
|
&cmd,
|
||||||
D3D12InputImage {
|
D3D12InputImage::Managed(self.texture.to_ref()),
|
||||||
resource: self.texture.to_ref(),
|
|
||||||
descriptor: None,
|
|
||||||
},
|
|
||||||
&viewport,
|
&viewport,
|
||||||
frame,
|
frame,
|
||||||
options.as_ref(),
|
options.as_ref(),
|
||||||
|
|
|
@ -67,7 +67,7 @@ pub struct FilterChainD3D12 {
|
||||||
pub(crate) output_framebuffers: Box<[OwnedImage]>,
|
pub(crate) output_framebuffers: Box<[OwnedImage]>,
|
||||||
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>,
|
pub(crate) staging_heap: D3D12DescriptorHeap<CpuStagingHeap>,
|
||||||
pub(crate) rtv_heap: D3D12DescriptorHeap<RenderTargetHeap>,
|
pub(crate) rtv_heap: D3D12DescriptorHeap<RenderTargetHeap>,
|
||||||
|
|
||||||
work_heap: ID3D12DescriptorHeap,
|
work_heap: ID3D12DescriptorHeap,
|
||||||
|
@ -735,7 +735,22 @@ impl FilterChainD3D12 {
|
||||||
Some(fbo.create_shader_resource_view(&mut self.staging_heap, filter, wrap_mode)?);
|
Some(fbo.create_shader_resource_view(&mut self.staging_heap, filter, wrap_mode)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
let original = unsafe { InputTexture::new_from_raw(input, filter, wrap_mode, &self.common.d3d12, &mut self.staging_heap)? };
|
let original = unsafe {
|
||||||
|
match input {
|
||||||
|
D3D12InputImage::Managed(input) => InputTexture::new_from_resource(
|
||||||
|
input,
|
||||||
|
filter,
|
||||||
|
wrap_mode,
|
||||||
|
&self.common.d3d12,
|
||||||
|
&mut self.staging_heap,
|
||||||
|
)?,
|
||||||
|
D3D12InputImage::External {
|
||||||
|
resource,
|
||||||
|
descriptor,
|
||||||
|
} => InputTexture::new_from_raw(resource, descriptor, filter, wrap_mode),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let mut source = original.clone();
|
let mut source = original.clone();
|
||||||
|
|
||||||
// swap output and feedback **before** recording command buffers
|
// swap output and feedback **before** recording command buffers
|
||||||
|
|
|
@ -27,10 +27,10 @@ use windows::Win32::Graphics::Direct3D12::{
|
||||||
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_RESOURCE_STATE_RENDER_TARGET, D3D12_SHADER_RESOURCE_VIEW_DESC,
|
||||||
D3D12_SHADER_RESOURCE_VIEW_DESC, D3D12_SHADER_RESOURCE_VIEW_DESC_0,
|
D3D12_SHADER_RESOURCE_VIEW_DESC_0, D3D12_SRV_DIMENSION_TEXTURE2D, D3D12_TEX2D_SRV,
|
||||||
D3D12_SRV_DIMENSION_TEXTURE2D, D3D12_TEX2D_SRV, D3D12_TEXTURE_COPY_LOCATION,
|
D3D12_TEXTURE_COPY_LOCATION, D3D12_TEXTURE_COPY_LOCATION_0,
|
||||||
D3D12_TEXTURE_COPY_LOCATION_0, D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
|
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};
|
||||||
|
|
||||||
|
@ -295,7 +295,7 @@ impl OwnedImage {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(InputTexture::new(
|
Ok(InputTexture::new_owned(
|
||||||
&self.resource,
|
&self.resource,
|
||||||
descriptor,
|
descriptor,
|
||||||
self.size,
|
self.size,
|
||||||
|
@ -309,7 +309,9 @@ impl OwnedImage {
|
||||||
&self,
|
&self,
|
||||||
heap: &mut D3D12DescriptorHeap<RenderTargetHeap>,
|
heap: &mut D3D12DescriptorHeap<RenderTargetHeap>,
|
||||||
) -> error::Result<D3D12OutputView> {
|
) -> error::Result<D3D12OutputView> {
|
||||||
D3D12OutputView::new_from_resource_internal(self.resource.to_ref(), &self.device, heap)
|
unsafe {
|
||||||
|
D3D12OutputView::new_from_resource_internal(self.resource.to_ref(), &self.device, heap)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scale(
|
pub fn scale(
|
||||||
|
|
|
@ -201,7 +201,7 @@ impl LutTexture {
|
||||||
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||||
);
|
);
|
||||||
|
|
||||||
let view = InputTexture::new(
|
let view = InputTexture::new_owned(
|
||||||
&resource,
|
&resource,
|
||||||
descriptor,
|
descriptor,
|
||||||
source.size,
|
source.size,
|
||||||
|
|
|
@ -1,14 +1,21 @@
|
||||||
use crate::descriptor_heap::{CpuStagingHeap, RenderTargetHeap};
|
use crate::descriptor_heap::{CpuStagingHeap, RenderTargetHeap};
|
||||||
use crate::{error, FilterChainD3D12};
|
use crate::error::FilterChainError;
|
||||||
use crate::resource::{OutlivesFrame, ResourceHandleStrategy};
|
use crate::resource::{OutlivesFrame, ResourceHandleStrategy};
|
||||||
|
use crate::{error, FilterChainD3D12};
|
||||||
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 std::ops::Deref;
|
||||||
use windows::core::InterfaceRef;
|
use windows::core::InterfaceRef;
|
||||||
use windows::Win32::Graphics::Direct3D12::{ID3D12Device, ID3D12Resource, D3D12_CPU_DESCRIPTOR_HANDLE, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING, D3D12_RENDER_TARGET_VIEW_DESC, D3D12_RENDER_TARGET_VIEW_DESC_0, D3D12_RESOURCE_DIMENSION_TEXTURE2D, 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};
|
use windows::Win32::Graphics::Direct3D12::{
|
||||||
|
ID3D12Device, ID3D12Resource, D3D12_CPU_DESCRIPTOR_HANDLE,
|
||||||
|
D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING, D3D12_RENDER_TARGET_VIEW_DESC,
|
||||||
|
D3D12_RENDER_TARGET_VIEW_DESC_0, D3D12_RESOURCE_DIMENSION_TEXTURE2D,
|
||||||
|
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,
|
||||||
|
};
|
||||||
use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT;
|
use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT;
|
||||||
use crate::error::FilterChainError;
|
|
||||||
|
|
||||||
/// A **non-owning** reference to a ID3D12Resource.
|
/// A **non-owning** reference to a ID3D12Resource.
|
||||||
/// This does not `AddRef` or `Release` the underlying interface.
|
/// This does not `AddRef` or `Release` the underlying interface.
|
||||||
|
@ -16,18 +23,16 @@ 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 enum D3D12InputImage<'a> {
|
||||||
pub resource: InterfaceRef<'a, ID3D12Resource>,
|
/// The filter chain manages the CPU descriptor to the shader resource view.
|
||||||
pub descriptor: Option<D3D12_CPU_DESCRIPTOR_HANDLE>,
|
Managed(InterfaceRef<'a, ID3D12Resource>),
|
||||||
}
|
/// The CPU descriptor to the shader resource view is managed externally.
|
||||||
|
External {
|
||||||
impl<'a> From<InterfaceRef<'a, ID3D12Resource>> for D3D12InputImage<'a> {
|
/// The ID3D12Resource that holds the image data.
|
||||||
fn from(value: InterfaceRef<'a, ID3D12Resource>) -> Self {
|
resource: InterfaceRef<'a, ID3D12Resource>,
|
||||||
Self {
|
/// The CPU descriptor to the shader resource view.
|
||||||
resource: value,
|
descriptor: D3D12_CPU_DESCRIPTOR_HANDLE,
|
||||||
descriptor: None
|
},
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -85,6 +90,9 @@ impl D3D12OutputView {
|
||||||
}
|
}
|
||||||
|
|
||||||
// unsafe since the lifetime of the handle has to survive
|
// unsafe since the lifetime of the handle has to survive
|
||||||
|
/// Create a new D3D12OutputView from a CPU descriptor handle of a render target view.
|
||||||
|
///
|
||||||
|
/// SAFETY: the handle must be valid until the command list is submitted.
|
||||||
pub unsafe fn new_from_raw(
|
pub unsafe fn new_from_raw(
|
||||||
handle: D3D12_CPU_DESCRIPTOR_HANDLE,
|
handle: D3D12_CPU_DESCRIPTOR_HANDLE,
|
||||||
size: Size<u32>,
|
size: Size<u32>,
|
||||||
|
@ -101,15 +109,17 @@ impl D3D12OutputView {
|
||||||
/// Create a new output view from a resource ref, linked to the chain.
|
/// Create a new output view from a resource ref, linked to the chain.
|
||||||
///
|
///
|
||||||
/// The output view will be automatically disposed on drop.
|
/// The output view will be automatically disposed on drop.
|
||||||
pub fn new_from_resource(
|
///
|
||||||
|
/// SAFETY: the image must be valid until the command list is submitted.
|
||||||
|
pub unsafe fn new_from_resource(
|
||||||
image: D3D12ResourceRef,
|
image: D3D12ResourceRef,
|
||||||
chain: &mut FilterChainD3D12
|
chain: &mut FilterChainD3D12,
|
||||||
) -> error::Result<D3D12OutputView> {
|
) -> error::Result<D3D12OutputView> {
|
||||||
Self::new_from_resource_internal(image, &chain.common.d3d12, &mut chain.rtv_heap)
|
unsafe { Self::new_from_resource_internal(image, &chain.common.d3d12, &mut chain.rtv_heap) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new output view from a resource ref
|
/// Create a new output view from a resource ref
|
||||||
pub(crate) fn new_from_resource_internal(
|
pub(crate) unsafe fn new_from_resource_internal(
|
||||||
image: D3D12ResourceRef,
|
image: D3D12ResourceRef,
|
||||||
device: &ID3D12Device,
|
device: &ID3D12Device,
|
||||||
heap: &mut D3D12DescriptorHeap<RenderTargetHeap>,
|
heap: &mut D3D12DescriptorHeap<RenderTargetHeap>,
|
||||||
|
@ -145,7 +155,7 @@ impl D3D12OutputView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct InputTexture {
|
pub(crate) struct InputTexture {
|
||||||
pub(crate) resource: ManuallyDrop<ID3D12Resource>,
|
pub(crate) resource: ManuallyDrop<ID3D12Resource>,
|
||||||
pub(crate) descriptor: InputDescriptor,
|
pub(crate) descriptor: InputDescriptor,
|
||||||
pub(crate) size: Size<u32>,
|
pub(crate) size: Size<u32>,
|
||||||
|
@ -157,7 +167,7 @@ pub struct InputTexture {
|
||||||
impl InputTexture {
|
impl InputTexture {
|
||||||
// Create a new input texture, with runtime lifetime tracking.
|
// Create a new input texture, with runtime lifetime tracking.
|
||||||
// The source owned framebuffer must outlive this input.
|
// The source owned framebuffer must outlive this input.
|
||||||
pub fn new(
|
pub fn new_owned(
|
||||||
resource: &ManuallyDrop<ID3D12Resource>,
|
resource: &ManuallyDrop<ID3D12Resource>,
|
||||||
handle: D3D12DescriptorHeapSlot<CpuStagingHeap>,
|
handle: D3D12DescriptorHeapSlot<CpuStagingHeap>,
|
||||||
size: Size<u32>,
|
size: Size<u32>,
|
||||||
|
@ -168,7 +178,7 @@ impl InputTexture {
|
||||||
let srv = InputDescriptor::Owned(handle);
|
let srv = InputDescriptor::Owned(handle);
|
||||||
InputTexture {
|
InputTexture {
|
||||||
// SAFETY: `new` is only used for owned textures. We know this because
|
// SAFETY: `new` is only used for owned textures. We know this because
|
||||||
// we also hold `handle`, so the texture is at least
|
// we also hold `handle`, so the texture must be valid for at least
|
||||||
// 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.
|
||||||
|
@ -182,19 +192,19 @@ 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_resource<'a>(
|
||||||
image: D3D12InputImage,
|
image: InterfaceRef<'a, ID3D12Resource>,
|
||||||
filter: FilterMode,
|
filter: FilterMode,
|
||||||
wrap_mode: WrapMode,
|
wrap_mode: WrapMode,
|
||||||
device: &ID3D12Device,
|
device: &ID3D12Device,
|
||||||
heap: &mut D3D12DescriptorHeap<CpuStagingHeap>,
|
heap: &mut D3D12DescriptorHeap<CpuStagingHeap>,
|
||||||
) -> error::Result<InputTexture> {
|
) -> error::Result<InputTexture> {
|
||||||
let desc = unsafe { image.resource.GetDesc() };
|
let desc = unsafe { image.GetDesc() };
|
||||||
if desc.Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE2D {
|
if desc.Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE2D {
|
||||||
return Err(FilterChainError::InvalidDimensionError(desc.Dimension));
|
return Err(FilterChainError::InvalidDimensionError(desc.Dimension));
|
||||||
}
|
}
|
||||||
|
|
||||||
let descriptor = image.descriptor.map_or_else(|| {
|
let descriptor = {
|
||||||
let slot = heap.allocate_descriptor()?;
|
let slot = heap.allocate_descriptor()?;
|
||||||
unsafe {
|
unsafe {
|
||||||
let srv_desc = D3D12_SHADER_RESOURCE_VIEW_DESC {
|
let srv_desc = D3D12_SHADER_RESOURCE_VIEW_DESC {
|
||||||
|
@ -208,14 +218,14 @@ impl InputTexture {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
device.CreateShaderResourceView(image.resource.deref(), Some(&srv_desc), *slot.as_ref());
|
device.CreateShaderResourceView(image.deref(), Some(&srv_desc), *slot.as_ref());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok::<_, FilterChainError>(InputDescriptor::Owned(slot))
|
Ok::<_, FilterChainError>(InputDescriptor::Owned(slot))
|
||||||
}, |raw| Ok(InputDescriptor::Raw(raw)))?;
|
}?;
|
||||||
|
|
||||||
Ok(InputTexture {
|
Ok(InputTexture {
|
||||||
resource: unsafe { std::mem::transmute(image.resource) },
|
resource: unsafe { std::mem::transmute(image) },
|
||||||
descriptor,
|
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,
|
||||||
|
@ -224,7 +234,23 @@ impl InputTexture {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// unsafe since the lifetime of the handle has to survive
|
||||||
|
pub unsafe fn new_from_raw(
|
||||||
|
image: InterfaceRef<ID3D12Resource>,
|
||||||
|
descriptor: D3D12_CPU_DESCRIPTOR_HANDLE,
|
||||||
|
filter: FilterMode,
|
||||||
|
wrap_mode: WrapMode,
|
||||||
|
) -> InputTexture {
|
||||||
|
let desc = unsafe { image.GetDesc() };
|
||||||
|
InputTexture {
|
||||||
|
resource: unsafe { std::mem::transmute(image) },
|
||||||
|
descriptor: InputDescriptor::Raw(descriptor),
|
||||||
|
size: Size::new(desc.Width as u32, desc.Height),
|
||||||
|
format: desc.Format,
|
||||||
|
wrap_mode,
|
||||||
|
filter,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for InputTexture {
|
impl Clone for InputTexture {
|
||||||
|
|
Loading…
Reference in a new issue