rt(d3d12): make images with OwnedFramebuffer provenance use ManuallyDrop
This commit is contained in:
parent
7edff0ae35
commit
c57e502b78
|
@ -131,13 +131,18 @@ impl FrameResiduals {
|
||||||
self.mipmaps.extend(handles)
|
self.mipmaps.extend(handles)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dispose_resource(&mut self, resource: ManuallyDrop<Option<ID3D12Resource>>) {
|
pub unsafe fn dispose_resource(&mut self, resource: ManuallyDrop<Option<ID3D12Resource>>) {
|
||||||
self.resources.push(resource)
|
self.resources.push(resource)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Disposition only handles transition barriers, but it is not unsafe because
|
/// Disposition only handles transition barriers.
|
||||||
/// other things just leak and leakign is not unsafe,
|
///
|
||||||
pub fn dispose_barriers(&mut self, barrier: impl IntoIterator<Item = D3D12_RESOURCE_BARRIER>) {
|
/// **Safety:** It is only safe to dispose a barrier created with resource strategy IncrementRef.
|
||||||
|
///
|
||||||
|
pub unsafe fn dispose_barriers(
|
||||||
|
&mut self,
|
||||||
|
barrier: impl IntoIterator<Item = D3D12_RESOURCE_BARRIER>,
|
||||||
|
) {
|
||||||
self.resource_barriers.extend(barrier);
|
self.resource_barriers.extend(barrier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,6 +235,7 @@ mod compile {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use crate::resource::OutlivesFrame;
|
||||||
use compile::{compile_passes_dxil, compile_passes_hlsl, DxilShaderPassMeta, HlslShaderPassMeta};
|
use compile::{compile_passes_dxil, compile_passes_hlsl, DxilShaderPassMeta, HlslShaderPassMeta};
|
||||||
use librashader_runtime::parameters::RuntimeParameters;
|
use librashader_runtime::parameters::RuntimeParameters;
|
||||||
|
|
||||||
|
@ -321,7 +327,8 @@ impl FilterChainD3D12 {
|
||||||
let mut staging_heap = unsafe {
|
let mut staging_heap = unsafe {
|
||||||
D3D12DescriptorHeap::new(
|
D3D12DescriptorHeap::new(
|
||||||
device,
|
device,
|
||||||
(MAX_BINDINGS_COUNT as usize) * shader_count
|
// add one, because technically the input image doesn't need to count
|
||||||
|
(1 + MAX_BINDINGS_COUNT as usize) * shader_count
|
||||||
+ MIPMAP_RESERVED_WORKHEAP_DESCRIPTORS
|
+ MIPMAP_RESERVED_WORKHEAP_DESCRIPTORS
|
||||||
+ lut_count,
|
+ lut_count,
|
||||||
)
|
)
|
||||||
|
@ -391,7 +398,7 @@ impl FilterChainD3D12 {
|
||||||
common: FilterCommon {
|
common: FilterCommon {
|
||||||
d3d12: device.clone(),
|
d3d12: device.clone(),
|
||||||
samplers,
|
samplers,
|
||||||
allocator: allocator,
|
allocator,
|
||||||
output_textures,
|
output_textures,
|
||||||
feedback_textures,
|
feedback_textures,
|
||||||
luts,
|
luts,
|
||||||
|
@ -460,7 +467,10 @@ impl FilterChainD3D12 {
|
||||||
|
|
||||||
gc.dispose_mipmap_handles(residual_mipmap);
|
gc.dispose_mipmap_handles(residual_mipmap);
|
||||||
gc.dispose_mipmap_gen(mipmap_gen);
|
gc.dispose_mipmap_gen(mipmap_gen);
|
||||||
gc.dispose_barriers(residual_barrier);
|
|
||||||
|
unsafe {
|
||||||
|
gc.dispose_barriers(residual_barrier);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(luts)
|
Ok(luts)
|
||||||
}
|
}
|
||||||
|
@ -653,7 +663,7 @@ impl FilterChainD3D12 {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
back.copy_from(cmd, input, &mut self.residuals)?;
|
back.copy_from(cmd, input)?;
|
||||||
}
|
}
|
||||||
self.history_framebuffers.push_front(back);
|
self.history_framebuffers.push_front(back);
|
||||||
}
|
}
|
||||||
|
@ -669,6 +679,8 @@ impl FilterChainD3D12 {
|
||||||
/// librashader **will not** create a resource barrier for the final pass. The output image will
|
/// librashader **will not** create a resource barrier for the final pass. The output image will
|
||||||
/// remain in `D3D12_RESOURCE_STATE_RENDER_TARGET` after all shader passes. The caller must transition
|
/// remain in `D3D12_RESOURCE_STATE_RENDER_TARGET` after all shader passes. The caller must transition
|
||||||
/// the output image to the final resource state.
|
/// the output image to the final resource state.
|
||||||
|
///
|
||||||
|
/// The input and output images must stay alive until the command list is submitted and work is complete.
|
||||||
pub unsafe fn frame(
|
pub unsafe fn frame(
|
||||||
&mut self,
|
&mut self,
|
||||||
cmd: &ID3D12GraphicsCommandList,
|
cmd: &ID3D12GraphicsCommandList,
|
||||||
|
@ -689,7 +701,7 @@ impl FilterChainD3D12 {
|
||||||
if let Some(options) = options {
|
if let Some(options) = options {
|
||||||
if options.clear_history {
|
if options.clear_history {
|
||||||
for framebuffer in &mut self.history_framebuffers {
|
for framebuffer in &mut self.history_framebuffers {
|
||||||
framebuffer.clear(cmd, &mut self.rtv_heap, &mut self.residuals)?;
|
framebuffer.clear(cmd, &mut self.rtv_heap)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -787,13 +799,12 @@ impl FilterChainD3D12 {
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.residuals
|
util::d3d12_resource_transition::<OutlivesFrame, _>(
|
||||||
.dispose_barriers(util::d3d12_resource_transition(
|
cmd,
|
||||||
cmd,
|
&target.resource,
|
||||||
&target.handle.resource(),
|
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||||
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
D3D12_RESOURCE_STATE_RENDER_TARGET,
|
||||||
D3D12_RESOURCE_STATE_RENDER_TARGET,
|
);
|
||||||
));
|
|
||||||
|
|
||||||
let view = target.create_render_target_view(&mut self.rtv_heap)?;
|
let view = target.create_render_target_view(&mut self.rtv_heap)?;
|
||||||
let out = RenderTarget::identity(&view)?;
|
let out = RenderTarget::identity(&view)?;
|
||||||
|
@ -811,21 +822,21 @@ impl FilterChainD3D12 {
|
||||||
QuadType::Offscreen,
|
QuadType::Offscreen,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.residuals
|
util::d3d12_resource_transition::<OutlivesFrame, _>(
|
||||||
.dispose_barriers(util::d3d12_resource_transition(
|
cmd,
|
||||||
cmd,
|
&target.resource,
|
||||||
&target.handle.resource(),
|
D3D12_RESOURCE_STATE_RENDER_TARGET,
|
||||||
D3D12_RESOURCE_STATE_RENDER_TARGET,
|
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||||
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
);
|
||||||
));
|
|
||||||
|
|
||||||
if target.max_mipmap > 1 && !self.disable_mipmaps {
|
if target.max_mipmap > 1 && !self.disable_mipmaps {
|
||||||
let (residuals, residual_barriers) = self.common.mipmap_gen.mipmapping_context(
|
// barriers don't get disposed because the context is OutlivesFrame
|
||||||
|
let (residuals, _residual_barriers) = self.common.mipmap_gen.mipmapping_context(
|
||||||
cmd,
|
cmd,
|
||||||
&mut self.mipmap_heap,
|
&mut self.mipmap_heap,
|
||||||
|ctx| {
|
|ctx| {
|
||||||
ctx.generate_mipmaps(
|
ctx.generate_mipmaps::<OutlivesFrame, _>(
|
||||||
&target.handle.resource(),
|
&target.resource,
|
||||||
target.max_mipmap,
|
target.max_mipmap,
|
||||||
target.size,
|
target.size,
|
||||||
target.format.into(),
|
target.format.into(),
|
||||||
|
@ -835,7 +846,6 @@ impl FilterChainD3D12 {
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.residuals.dispose_mipmap_handles(residuals);
|
self.residuals.dispose_mipmap_handles(residuals);
|
||||||
self.residuals.dispose_barriers(residual_barriers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.residuals.dispose_output(view.descriptor);
|
self.residuals.dispose_output(view.descriptor);
|
||||||
|
@ -862,13 +872,12 @@ impl FilterChainD3D12 {
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.residuals
|
util::d3d12_resource_transition::<OutlivesFrame, _>(
|
||||||
.dispose_barriers(util::d3d12_resource_transition(
|
cmd,
|
||||||
cmd,
|
&feedback_target.resource,
|
||||||
&feedback_target.handle.resource(),
|
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||||
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
D3D12_RESOURCE_STATE_RENDER_TARGET,
|
||||||
D3D12_RESOURCE_STATE_RENDER_TARGET,
|
);
|
||||||
));
|
|
||||||
|
|
||||||
let view = feedback_target.create_render_target_view(&mut self.rtv_heap)?;
|
let view = feedback_target.create_render_target_view(&mut self.rtv_heap)?;
|
||||||
let out = RenderTarget::viewport_with_output(&view, viewport);
|
let out = RenderTarget::viewport_with_output(&view, viewport);
|
||||||
|
@ -885,13 +894,12 @@ impl FilterChainD3D12 {
|
||||||
QuadType::Final,
|
QuadType::Final,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.residuals
|
util::d3d12_resource_transition::<OutlivesFrame, _>(
|
||||||
.dispose_barriers(util::d3d12_resource_transition(
|
cmd,
|
||||||
cmd,
|
&feedback_target.resource,
|
||||||
&feedback_target.handle.resource(),
|
D3D12_RESOURCE_STATE_RENDER_TARGET,
|
||||||
D3D12_RESOURCE_STATE_RENDER_TARGET,
|
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||||
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
);
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if pass.pipeline.format != viewport.output.format {
|
if pass.pipeline.format != viewport.output.format {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::descriptor_heap::{CpuStagingHeap, RenderTargetHeap};
|
use crate::descriptor_heap::{CpuStagingHeap, RenderTargetHeap};
|
||||||
use crate::error::FilterChainError;
|
use crate::error::FilterChainError;
|
||||||
use crate::filter_chain::FrameResiduals;
|
use crate::resource::{OutlivesFrame, ResourceHandleStrategy};
|
||||||
use crate::texture::{D3D12OutputView, InputTexture};
|
use crate::texture::{D3D12OutputView, InputTexture};
|
||||||
use crate::util::d3d12_get_closest_format;
|
use crate::util::d3d12_get_closest_format;
|
||||||
use crate::{error, util};
|
use crate::{error, util};
|
||||||
|
@ -17,12 +17,13 @@ use parking_lot::Mutex;
|
||||||
use std::mem::ManuallyDrop;
|
use std::mem::ManuallyDrop;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use windows::Win32::Graphics::Direct3D12::{
|
use windows::Win32::Graphics::Direct3D12::{
|
||||||
ID3D12Device, ID3D12GraphicsCommandList, D3D12_BOX, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
|
ID3D12Device, ID3D12GraphicsCommandList, ID3D12Resource, D3D12_BOX,
|
||||||
D3D12_FEATURE_DATA_FORMAT_SUPPORT, D3D12_FORMAT_SUPPORT1_MIP,
|
D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING, D3D12_FEATURE_DATA_FORMAT_SUPPORT,
|
||||||
D3D12_FORMAT_SUPPORT1_RENDER_TARGET, D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE,
|
D3D12_FORMAT_SUPPORT1_MIP, D3D12_FORMAT_SUPPORT1_RENDER_TARGET,
|
||||||
D3D12_FORMAT_SUPPORT1_TEXTURE2D, D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD,
|
D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE, D3D12_FORMAT_SUPPORT1_TEXTURE2D,
|
||||||
D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE, D3D12_RENDER_TARGET_VIEW_DESC,
|
D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD, D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE,
|
||||||
D3D12_RENDER_TARGET_VIEW_DESC_0, D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, D3D12_RESOURCE_DESC,
|
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_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,
|
||||||
|
@ -36,6 +37,7 @@ use windows::Win32::Graphics::Dxgi::Common::{DXGI_FORMAT, DXGI_SAMPLE_DESC};
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct OwnedImage {
|
pub(crate) struct OwnedImage {
|
||||||
pub(crate) handle: ManuallyDrop<Resource>,
|
pub(crate) handle: ManuallyDrop<Resource>,
|
||||||
|
pub(crate) resource: ManuallyDrop<ID3D12Resource>,
|
||||||
pub(crate) size: Size<u32>,
|
pub(crate) size: Size<u32>,
|
||||||
pub(crate) format: DXGI_FORMAT,
|
pub(crate) format: DXGI_FORMAT,
|
||||||
pub(crate) max_mipmap: u16,
|
pub(crate) max_mipmap: u16,
|
||||||
|
@ -113,7 +115,7 @@ impl OwnedImage {
|
||||||
|
|
||||||
desc.Format = d3d12_get_closest_format(device, format_support);
|
desc.Format = d3d12_get_closest_format(device, format_support);
|
||||||
|
|
||||||
let resource = allocator.lock().create_resource(&ResourceCreateDesc {
|
let allocator_resource = allocator.lock().create_resource(&ResourceCreateDesc {
|
||||||
name: "ownedimage",
|
name: "ownedimage",
|
||||||
memory_location: MemoryLocation::GpuOnly,
|
memory_location: MemoryLocation::GpuOnly,
|
||||||
resource_category: ResourceCategory::RtvDsvTexture,
|
resource_category: ResourceCategory::RtvDsvTexture,
|
||||||
|
@ -145,8 +147,10 @@ impl OwnedImage {
|
||||||
// }
|
// }
|
||||||
// assume_d3d12_init!(resource, "CreateCommittedResource");
|
// assume_d3d12_init!(resource, "CreateCommittedResource");
|
||||||
|
|
||||||
|
let resource = ManuallyDrop::new(allocator_resource.resource().clone());
|
||||||
Ok(OwnedImage {
|
Ok(OwnedImage {
|
||||||
handle: ManuallyDrop::new(resource),
|
handle: ManuallyDrop::new(allocator_resource),
|
||||||
|
resource,
|
||||||
size,
|
size,
|
||||||
format: desc.Format,
|
format: desc.Format,
|
||||||
device: device.clone(),
|
device: device.clone(),
|
||||||
|
@ -161,17 +165,16 @@ impl OwnedImage {
|
||||||
&self,
|
&self,
|
||||||
cmd: &ID3D12GraphicsCommandList,
|
cmd: &ID3D12GraphicsCommandList,
|
||||||
input: &InputTexture,
|
input: &InputTexture,
|
||||||
gc: &mut FrameResiduals,
|
|
||||||
) -> error::Result<()> {
|
) -> error::Result<()> {
|
||||||
let barriers = [
|
let barriers = [
|
||||||
util::d3d12_get_resource_transition_subresource(
|
util::d3d12_get_resource_transition_subresource::<OutlivesFrame, _>(
|
||||||
&input.resource,
|
&input.resource,
|
||||||
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||||
D3D12_RESOURCE_STATE_COPY_SOURCE,
|
D3D12_RESOURCE_STATE_COPY_SOURCE,
|
||||||
D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
|
D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
|
||||||
),
|
),
|
||||||
util::d3d12_get_resource_transition_subresource(
|
util::d3d12_get_resource_transition_subresource::<OutlivesFrame, _>(
|
||||||
&self.handle.resource(),
|
&self.resource,
|
||||||
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||||
D3D12_RESOURCE_STATE_COPY_DEST,
|
D3D12_RESOURCE_STATE_COPY_DEST,
|
||||||
D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
|
D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
|
||||||
|
@ -180,10 +183,9 @@ impl OwnedImage {
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
cmd.ResourceBarrier(&barriers);
|
cmd.ResourceBarrier(&barriers);
|
||||||
gc.dispose_barriers(barriers);
|
|
||||||
|
|
||||||
let dst = D3D12_TEXTURE_COPY_LOCATION {
|
let dst = D3D12_TEXTURE_COPY_LOCATION {
|
||||||
pResource: ManuallyDrop::new(Some(self.handle.resource().clone())),
|
pResource: OutlivesFrame::obtain(&self.resource),
|
||||||
Type: D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
|
Type: D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
|
||||||
Anonymous: D3D12_TEXTURE_COPY_LOCATION_0 {
|
Anonymous: D3D12_TEXTURE_COPY_LOCATION_0 {
|
||||||
SubresourceIndex: 0,
|
SubresourceIndex: 0,
|
||||||
|
@ -191,7 +193,7 @@ impl OwnedImage {
|
||||||
};
|
};
|
||||||
|
|
||||||
let src = D3D12_TEXTURE_COPY_LOCATION {
|
let src = D3D12_TEXTURE_COPY_LOCATION {
|
||||||
pResource: ManuallyDrop::new(Some(input.resource.clone())),
|
pResource: OutlivesFrame::obtain(&input.resource),
|
||||||
Type: D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
|
Type: D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
|
||||||
Anonymous: D3D12_TEXTURE_COPY_LOCATION_0 {
|
Anonymous: D3D12_TEXTURE_COPY_LOCATION_0 {
|
||||||
SubresourceIndex: 0,
|
SubresourceIndex: 0,
|
||||||
|
@ -213,20 +215,17 @@ impl OwnedImage {
|
||||||
back: 1,
|
back: 1,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
gc.dispose_resource(dst.pResource);
|
|
||||||
gc.dispose_resource(src.pResource);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let barriers = [
|
let barriers = [
|
||||||
util::d3d12_get_resource_transition_subresource(
|
util::d3d12_get_resource_transition_subresource::<OutlivesFrame, _>(
|
||||||
&input.resource,
|
&input.resource,
|
||||||
D3D12_RESOURCE_STATE_COPY_SOURCE,
|
D3D12_RESOURCE_STATE_COPY_SOURCE,
|
||||||
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||||
D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
|
D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
|
||||||
),
|
),
|
||||||
util::d3d12_get_resource_transition_subresource(
|
util::d3d12_get_resource_transition_subresource::<OutlivesFrame, _>(
|
||||||
&self.handle.resource(),
|
&self.resource,
|
||||||
D3D12_RESOURCE_STATE_COPY_DEST,
|
D3D12_RESOURCE_STATE_COPY_DEST,
|
||||||
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||||
D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
|
D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
|
||||||
|
@ -237,8 +236,6 @@ impl OwnedImage {
|
||||||
cmd.ResourceBarrier(&barriers);
|
cmd.ResourceBarrier(&barriers);
|
||||||
}
|
}
|
||||||
|
|
||||||
gc.dispose_barriers(barriers);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,25 +243,26 @@ impl OwnedImage {
|
||||||
&self,
|
&self,
|
||||||
cmd: &ID3D12GraphicsCommandList,
|
cmd: &ID3D12GraphicsCommandList,
|
||||||
heap: &mut D3D12DescriptorHeap<RenderTargetHeap>,
|
heap: &mut D3D12DescriptorHeap<RenderTargetHeap>,
|
||||||
gc: &mut FrameResiduals,
|
|
||||||
) -> error::Result<()> {
|
) -> error::Result<()> {
|
||||||
gc.dispose_barriers(util::d3d12_resource_transition(
|
unsafe {
|
||||||
cmd,
|
util::d3d12_resource_transition::<OutlivesFrame, _>(
|
||||||
&self.handle.resource(),
|
cmd,
|
||||||
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
&self.resource,
|
||||||
D3D12_RESOURCE_STATE_RENDER_TARGET,
|
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||||
));
|
D3D12_RESOURCE_STATE_RENDER_TARGET,
|
||||||
|
);
|
||||||
|
|
||||||
let rtv = self.create_render_target_view(heap)?;
|
let rtv = self.create_render_target_view(heap)?;
|
||||||
|
|
||||||
unsafe { cmd.ClearRenderTargetView(*rtv.descriptor.as_ref(), CLEAR, None) }
|
cmd.ClearRenderTargetView(*rtv.descriptor.as_ref(), CLEAR, None);
|
||||||
|
|
||||||
gc.dispose_barriers(util::d3d12_resource_transition(
|
util::d3d12_resource_transition::<OutlivesFrame, _>(
|
||||||
cmd,
|
cmd,
|
||||||
&self.handle.resource(),
|
&self.resource,
|
||||||
D3D12_RESOURCE_STATE_RENDER_TARGET,
|
D3D12_RESOURCE_STATE_RENDER_TARGET,
|
||||||
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||||
));
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -297,8 +295,8 @@ impl OwnedImage {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(InputTexture::new(
|
Ok(InputTexture::new::<OutlivesFrame, _>(
|
||||||
self.handle.resource().clone(),
|
&self.resource,
|
||||||
descriptor,
|
descriptor,
|
||||||
self.size,
|
self.size,
|
||||||
self.format,
|
self.format,
|
||||||
|
@ -390,6 +388,10 @@ impl ScaleFramebuffer for OwnedImage {
|
||||||
|
|
||||||
impl Drop for OwnedImage {
|
impl Drop for OwnedImage {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
|
// let go of the handle
|
||||||
|
unsafe {
|
||||||
|
ManuallyDrop::drop(&mut self.resource);
|
||||||
|
}
|
||||||
let resource = unsafe { ManuallyDrop::take(&mut self.handle) };
|
let resource = unsafe { ManuallyDrop::take(&mut self.handle) };
|
||||||
if let Err(e) = self.allocator.lock().free_resource(resource) {
|
if let Err(e) = self.allocator.lock().free_resource(resource) {
|
||||||
println!("librashader-runtime-d3d12: [warn] failed to deallocate owned image buffer memory {e}")
|
println!("librashader-runtime-d3d12: [warn] failed to deallocate owned image buffer memory {e}")
|
||||||
|
|
|
@ -176,12 +176,12 @@ impl LutTexture {
|
||||||
let resource = ManuallyDrop::new(allocator_resource.resource().clone());
|
let resource = ManuallyDrop::new(allocator_resource.resource().clone());
|
||||||
let upload = ManuallyDrop::new(allocator_upload.resource().clone());
|
let upload = ManuallyDrop::new(allocator_upload.resource().clone());
|
||||||
|
|
||||||
gc.dispose_barriers(d3d12_resource_transition(
|
d3d12_resource_transition::<OutlivesFrame, _>(
|
||||||
cmd,
|
cmd,
|
||||||
&allocator_resource.resource(),
|
&resource,
|
||||||
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||||
D3D12_RESOURCE_STATE_COPY_DEST,
|
D3D12_RESOURCE_STATE_COPY_DEST,
|
||||||
));
|
);
|
||||||
|
|
||||||
d3d12_update_subresources::<OutlivesFrame>(
|
d3d12_update_subresources::<OutlivesFrame>(
|
||||||
cmd,
|
cmd,
|
||||||
|
@ -194,15 +194,15 @@ impl LutTexture {
|
||||||
gc,
|
gc,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
gc.dispose_barriers(d3d12_resource_transition(
|
d3d12_resource_transition::<OutlivesFrame, _>(
|
||||||
cmd,
|
cmd,
|
||||||
&resource,
|
&resource,
|
||||||
D3D12_RESOURCE_STATE_COPY_DEST,
|
D3D12_RESOURCE_STATE_COPY_DEST,
|
||||||
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||||
));
|
);
|
||||||
|
|
||||||
let view = InputTexture::new(
|
let view = InputTexture::new::<OutlivesFrame, _>(
|
||||||
allocator_resource.resource().clone(),
|
&resource,
|
||||||
descriptor,
|
descriptor,
|
||||||
source.size,
|
source.size,
|
||||||
ImageFormat::R8G8B8A8Unorm.into(),
|
ImageFormat::R8G8B8A8Unorm.into(),
|
||||||
|
@ -223,8 +223,8 @@ impl LutTexture {
|
||||||
|
|
||||||
pub fn generate_mipmaps(&self, gen_mips: &mut MipmapGenContext) -> error::Result<()> {
|
pub fn generate_mipmaps(&self, gen_mips: &mut MipmapGenContext) -> error::Result<()> {
|
||||||
if let Some(miplevels) = self.miplevels {
|
if let Some(miplevels) = self.miplevels {
|
||||||
gen_mips.generate_mipmaps(
|
gen_mips.generate_mipmaps::<OutlivesFrame, _>(
|
||||||
&self.allocator_resource.resource(),
|
&self.resource,
|
||||||
miplevels,
|
miplevels,
|
||||||
self.view.size,
|
self.view.size,
|
||||||
ImageFormat::R8G8B8A8Unorm.into(),
|
ImageFormat::R8G8B8A8Unorm.into(),
|
||||||
|
@ -384,8 +384,8 @@ fn update_subresources<S: ResourceHandleStrategy<ManuallyDrop<ID3D12Resource>>>(
|
||||||
|
|
||||||
cmd.CopyTextureRegion(&dest_location, 0, 0, 0, &source_location, None);
|
cmd.CopyTextureRegion(&dest_location, 0, 0, 0, &source_location, None);
|
||||||
|
|
||||||
S::cleanup(gc, dest_location.pResource);
|
S::cleanup_handler(|| gc.dispose_resource(dest_location.pResource));
|
||||||
S::cleanup(gc, source_location.pResource);
|
S::cleanup_handler(|| gc.dispose_resource(source_location.pResource));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(required_size)
|
Ok(required_size)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::descriptor_heap::ResourceWorkHeap;
|
use crate::descriptor_heap::ResourceWorkHeap;
|
||||||
|
use crate::resource::{ObtainResourceHandle, ResourceHandleStrategy};
|
||||||
use crate::util::dxc_validate_shader;
|
use crate::util::dxc_validate_shader;
|
||||||
use crate::{error, util};
|
use crate::{error, util};
|
||||||
use bytemuck::{Pod, Zeroable};
|
use bytemuck::{Pod, Zeroable};
|
||||||
|
@ -6,12 +7,13 @@ use d3d12_descriptor_heap::{D3D12DescriptorHeap, D3D12DescriptorHeapSlot};
|
||||||
use librashader_common::Size;
|
use librashader_common::Size;
|
||||||
use librashader_runtime::scaling::MipmapSize;
|
use librashader_runtime::scaling::MipmapSize;
|
||||||
use std::mem::ManuallyDrop;
|
use std::mem::ManuallyDrop;
|
||||||
|
|
||||||
use windows::Win32::Graphics::Direct3D::Dxc::{
|
use windows::Win32::Graphics::Direct3D::Dxc::{
|
||||||
CLSID_DxcLibrary, CLSID_DxcValidator, DxcCreateInstance,
|
CLSID_DxcLibrary, CLSID_DxcValidator, DxcCreateInstance,
|
||||||
};
|
};
|
||||||
use windows::Win32::Graphics::Direct3D12::{
|
use windows::Win32::Graphics::Direct3D12::{
|
||||||
ID3D12DescriptorHeap, ID3D12Device, ID3D12GraphicsCommandList, ID3D12PipelineState,
|
ID3D12DescriptorHeap, ID3D12Device, ID3D12GraphicsCommandList, ID3D12PipelineState,
|
||||||
ID3D12Resource, ID3D12RootSignature, D3D12_COMPUTE_PIPELINE_STATE_DESC,
|
ID3D12RootSignature, D3D12_COMPUTE_PIPELINE_STATE_DESC,
|
||||||
D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING, D3D12_RESOURCE_BARRIER, D3D12_RESOURCE_BARRIER_0,
|
D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING, D3D12_RESOURCE_BARRIER, D3D12_RESOURCE_BARRIER_0,
|
||||||
D3D12_RESOURCE_BARRIER_TYPE_UAV, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
D3D12_RESOURCE_BARRIER_TYPE_UAV, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||||
D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_UAV_BARRIER, D3D12_SHADER_BYTECODE,
|
D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_UAV_BARRIER, D3D12_SHADER_BYTECODE,
|
||||||
|
@ -62,9 +64,9 @@ impl<'a> MipmapGenContext<'a> {
|
||||||
|
|
||||||
/// Generate a set of mipmaps for the resource.
|
/// Generate a set of mipmaps for the resource.
|
||||||
/// This is a "cheap" action and only dispatches a compute shader.
|
/// This is a "cheap" action and only dispatches a compute shader.
|
||||||
pub fn generate_mipmaps(
|
pub fn generate_mipmaps<S: ResourceHandleStrategy<T>, T: ObtainResourceHandle>(
|
||||||
&mut self,
|
&mut self,
|
||||||
resource: &ID3D12Resource,
|
resource: &T,
|
||||||
miplevels: u16,
|
miplevels: u16,
|
||||||
size: Size<u32>,
|
size: Size<u32>,
|
||||||
format: DXGI_FORMAT,
|
format: DXGI_FORMAT,
|
||||||
|
@ -72,9 +74,13 @@ impl<'a> MipmapGenContext<'a> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let (residuals_heap, residual_barriers) = self
|
let (residuals_heap, residual_barriers) = self
|
||||||
.gen
|
.gen
|
||||||
.generate_mipmaps(self.cmd, resource, miplevels, size, format, self.heap)?;
|
.generate_mipmaps::<S, T>(self.cmd, resource, miplevels, size, format, self.heap)?;
|
||||||
|
|
||||||
|
// heap slots always need to be disposed
|
||||||
self.residuals.extend(residuals_heap);
|
self.residuals.extend(residuals_heap);
|
||||||
self.residual_barriers.extend(residual_barriers);
|
|
||||||
|
// barriers need to be disposed if the handle strategy is incrementref
|
||||||
|
S::cleanup_handler(|| self.residual_barriers.extend(residual_barriers));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -178,10 +184,10 @@ impl D3D12MipmapGen {
|
||||||
/// SAFETY:
|
/// SAFETY:
|
||||||
/// - handle must be a CPU handle to an SRV
|
/// - handle must be a CPU handle to an SRV
|
||||||
/// - work_heap must have enough descriptors to fit all miplevels.
|
/// - work_heap must have enough descriptors to fit all miplevels.
|
||||||
unsafe fn generate_mipmaps(
|
unsafe fn generate_mipmaps<S: ResourceHandleStrategy<T>, T: ObtainResourceHandle>(
|
||||||
&self,
|
&self,
|
||||||
cmd: &ID3D12GraphicsCommandList,
|
cmd: &ID3D12GraphicsCommandList,
|
||||||
resource: &ID3D12Resource,
|
resource: &T,
|
||||||
miplevels: u16,
|
miplevels: u16,
|
||||||
size: Size<u32>,
|
size: Size<u32>,
|
||||||
format: DXGI_FORMAT,
|
format: DXGI_FORMAT,
|
||||||
|
@ -206,7 +212,7 @@ impl D3D12MipmapGen {
|
||||||
};
|
};
|
||||||
|
|
||||||
self.device
|
self.device
|
||||||
.CreateShaderResourceView(resource, Some(&srv_desc), *srv.as_ref());
|
.CreateShaderResourceView(resource.handle(), Some(&srv_desc), *srv.as_ref());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut heap_slots = Vec::with_capacity(miplevels as usize);
|
let mut heap_slots = Vec::with_capacity(miplevels as usize);
|
||||||
|
@ -227,7 +233,7 @@ impl D3D12MipmapGen {
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
self.device.CreateUnorderedAccessView(
|
self.device.CreateUnorderedAccessView(
|
||||||
resource,
|
resource.handle(),
|
||||||
None,
|
None,
|
||||||
Some(&desc),
|
Some(&desc),
|
||||||
*descriptor.as_ref(),
|
*descriptor.as_ref(),
|
||||||
|
@ -251,13 +257,13 @@ impl D3D12MipmapGen {
|
||||||
let mipmap_params = bytemuck::bytes_of(&mipmap_params);
|
let mipmap_params = bytemuck::bytes_of(&mipmap_params);
|
||||||
|
|
||||||
let barriers = [
|
let barriers = [
|
||||||
util::d3d12_get_resource_transition_subresource(
|
util::d3d12_get_resource_transition_subresource::<S, _>(
|
||||||
resource,
|
resource,
|
||||||
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||||
D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
|
D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
|
||||||
i - 1,
|
i - 1,
|
||||||
),
|
),
|
||||||
util::d3d12_get_resource_transition_subresource(
|
util::d3d12_get_resource_transition_subresource::<S, _>(
|
||||||
resource,
|
resource,
|
||||||
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||||
D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
|
D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
|
||||||
|
@ -267,7 +273,8 @@ impl D3D12MipmapGen {
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
cmd.ResourceBarrier(&barriers);
|
cmd.ResourceBarrier(&barriers);
|
||||||
residual_barriers.extend(barriers);
|
|
||||||
|
S::cleanup_handler(|| residual_barriers.extend(barriers));
|
||||||
|
|
||||||
cmd.SetComputeRootDescriptorTable(1, *heap_slots[i as usize].as_ref());
|
cmd.SetComputeRootDescriptorTable(1, *heap_slots[i as usize].as_ref());
|
||||||
cmd.SetComputeRoot32BitConstants(
|
cmd.SetComputeRoot32BitConstants(
|
||||||
|
@ -285,7 +292,7 @@ impl D3D12MipmapGen {
|
||||||
}
|
}
|
||||||
|
|
||||||
let uav_barrier = ManuallyDrop::new(D3D12_RESOURCE_UAV_BARRIER {
|
let uav_barrier = ManuallyDrop::new(D3D12_RESOURCE_UAV_BARRIER {
|
||||||
pResource: ManuallyDrop::new(Some(resource.clone())),
|
pResource: unsafe { S::obtain(resource) },
|
||||||
});
|
});
|
||||||
|
|
||||||
let barriers = [
|
let barriers = [
|
||||||
|
@ -294,13 +301,13 @@ impl D3D12MipmapGen {
|
||||||
Anonymous: D3D12_RESOURCE_BARRIER_0 { UAV: uav_barrier },
|
Anonymous: D3D12_RESOURCE_BARRIER_0 { UAV: uav_barrier },
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
util::d3d12_get_resource_transition_subresource(
|
util::d3d12_get_resource_transition_subresource::<S, _>(
|
||||||
resource,
|
resource,
|
||||||
D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
|
D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
|
||||||
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||||
i,
|
i,
|
||||||
),
|
),
|
||||||
util::d3d12_get_resource_transition_subresource(
|
util::d3d12_get_resource_transition_subresource::<S, _>(
|
||||||
resource,
|
resource,
|
||||||
D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
|
D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
|
||||||
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||||
|
@ -312,7 +319,7 @@ impl D3D12MipmapGen {
|
||||||
cmd.ResourceBarrier(&barriers);
|
cmd.ResourceBarrier(&barriers);
|
||||||
}
|
}
|
||||||
|
|
||||||
residual_barriers.extend(barriers)
|
S::cleanup_handler(|| residual_barriers.extend(barriers));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((heap_slots, residual_barriers))
|
Ok((heap_slots, residual_barriers))
|
||||||
|
|
|
@ -1,37 +1,64 @@
|
||||||
use crate::filter_chain::FrameResiduals;
|
|
||||||
use std::mem::ManuallyDrop;
|
use std::mem::ManuallyDrop;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use windows::Win32::Graphics::Direct3D12::ID3D12Resource;
|
use windows::Win32::Graphics::Direct3D12::ID3D12Resource;
|
||||||
|
|
||||||
pub trait ResourceHandleStrategy<H> {
|
pub trait ResourceHandleStrategy<H> {
|
||||||
|
const NEEDS_CLEANUP: bool;
|
||||||
unsafe fn obtain(handle: &H) -> ManuallyDrop<Option<ID3D12Resource>>;
|
unsafe fn obtain(handle: &H) -> ManuallyDrop<Option<ID3D12Resource>>;
|
||||||
unsafe fn cleanup(gc: &mut FrameResiduals, handle: ManuallyDrop<Option<ID3D12Resource>>);
|
|
||||||
|
/// Run a clean-up handler if the resource type needs clean up.
|
||||||
|
fn cleanup_handler<F: FnOnce()>(cleanup_fn: F) {
|
||||||
|
if Self::NEEDS_CLEANUP {
|
||||||
|
cleanup_fn();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait ObtainResourceHandle {
|
||||||
|
fn handle(&self) -> &ID3D12Resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ObtainResourceHandle for ID3D12Resource {
|
||||||
|
fn handle(&self) -> &ID3D12Resource {
|
||||||
|
&self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ObtainResourceHandle for ManuallyDrop<ID3D12Resource> {
|
||||||
|
fn handle(&self) -> &ID3D12Resource {
|
||||||
|
self.deref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// this isn't actually used anymore but keep it around just in case.
|
||||||
pub struct IncrementRefcount;
|
pub struct IncrementRefcount;
|
||||||
|
|
||||||
impl ResourceHandleStrategy<ManuallyDrop<ID3D12Resource>> for IncrementRefcount {
|
impl ResourceHandleStrategy<ManuallyDrop<ID3D12Resource>> for IncrementRefcount {
|
||||||
|
const NEEDS_CLEANUP: bool = true;
|
||||||
|
|
||||||
unsafe fn obtain(
|
unsafe fn obtain(
|
||||||
handle: &ManuallyDrop<ID3D12Resource>,
|
handle: &ManuallyDrop<ID3D12Resource>,
|
||||||
) -> ManuallyDrop<Option<ID3D12Resource>> {
|
) -> ManuallyDrop<Option<ID3D12Resource>> {
|
||||||
ManuallyDrop::new(Some(handle.deref().clone()))
|
ManuallyDrop::new(Some(handle.deref().clone()))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn cleanup(gc: &mut FrameResiduals, handle: ManuallyDrop<Option<ID3D12Resource>>) {
|
impl ResourceHandleStrategy<ID3D12Resource> for IncrementRefcount {
|
||||||
gc.dispose_resource(handle);
|
const NEEDS_CLEANUP: bool = true;
|
||||||
|
|
||||||
|
unsafe fn obtain(handle: &ID3D12Resource) -> ManuallyDrop<Option<ID3D12Resource>> {
|
||||||
|
ManuallyDrop::new(Some(handle.clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct OutlivesFrame;
|
pub struct OutlivesFrame;
|
||||||
|
|
||||||
impl ResourceHandleStrategy<ManuallyDrop<ID3D12Resource>> for OutlivesFrame {
|
impl ResourceHandleStrategy<ManuallyDrop<ID3D12Resource>> for OutlivesFrame {
|
||||||
|
const NEEDS_CLEANUP: bool = false;
|
||||||
|
|
||||||
unsafe fn obtain(
|
unsafe fn obtain(
|
||||||
handle: &ManuallyDrop<ID3D12Resource>,
|
handle: &ManuallyDrop<ID3D12Resource>,
|
||||||
) -> ManuallyDrop<Option<ID3D12Resource>> {
|
) -> ManuallyDrop<Option<ID3D12Resource>> {
|
||||||
unsafe { std::mem::transmute_copy(handle) }
|
unsafe { std::mem::transmute_copy(handle) }
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn cleanup(_gc: &mut FrameResiduals, _handle: ManuallyDrop<Option<ID3D12Resource>>) {
|
|
||||||
// Since the lifetime is ensured for the lifetime of the filter chain strategy, do nothing
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
use crate::descriptor_heap::{CpuStagingHeap, RenderTargetHeap};
|
use crate::descriptor_heap::{CpuStagingHeap, RenderTargetHeap};
|
||||||
|
use crate::resource::ResourceHandleStrategy;
|
||||||
use d3d12_descriptor_heap::D3D12DescriptorHeapSlot;
|
use d3d12_descriptor_heap::D3D12DescriptorHeapSlot;
|
||||||
use librashader_common::{FilterMode, GetSize, Size, WrapMode};
|
use librashader_common::{FilterMode, GetSize, Size, WrapMode};
|
||||||
|
use std::mem::ManuallyDrop;
|
||||||
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;
|
||||||
|
|
||||||
|
@ -17,6 +19,12 @@ pub(crate) enum InputDescriptor {
|
||||||
Raw(D3D12_CPU_DESCRIPTOR_HANDLE),
|
Raw(D3D12_CPU_DESCRIPTOR_HANDLE),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl InputDescriptor {
|
||||||
|
fn is_raw(&self) -> bool {
|
||||||
|
matches!(self, InputDescriptor::Raw(_))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) enum OutputDescriptor {
|
pub(crate) enum OutputDescriptor {
|
||||||
Owned(D3D12DescriptorHeapSlot<RenderTargetHeap>),
|
Owned(D3D12DescriptorHeapSlot<RenderTargetHeap>),
|
||||||
|
@ -80,19 +88,19 @@ impl D3D12OutputView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct InputTexture {
|
pub struct InputTexture {
|
||||||
pub(crate) resource: ID3D12Resource,
|
pub(crate) resource: ManuallyDrop<ID3D12Resource>,
|
||||||
pub(crate) descriptor: InputDescriptor,
|
pub(crate) descriptor: InputDescriptor,
|
||||||
pub(crate) size: Size<u32>,
|
pub(crate) size: Size<u32>,
|
||||||
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(
|
pub fn new<S: ResourceHandleStrategy<T>, T>(
|
||||||
resource: ID3D12Resource,
|
resource: &T,
|
||||||
handle: D3D12DescriptorHeapSlot<CpuStagingHeap>,
|
handle: D3D12DescriptorHeapSlot<CpuStagingHeap>,
|
||||||
size: Size<u32>,
|
size: Size<u32>,
|
||||||
format: DXGI_FORMAT,
|
format: DXGI_FORMAT,
|
||||||
|
@ -101,12 +109,18 @@ impl InputTexture {
|
||||||
) -> InputTexture {
|
) -> InputTexture {
|
||||||
let srv = InputDescriptor::Owned(handle);
|
let srv = InputDescriptor::Owned(handle);
|
||||||
InputTexture {
|
InputTexture {
|
||||||
resource,
|
// SAFETY: `new` is only used for owned textures. We know this because
|
||||||
|
// we also hold `handle`, so the texture is at least
|
||||||
|
// as valid for the lifetime of handle.
|
||||||
|
// Also, resource is non-null by construction.
|
||||||
|
// Option<T> and <T> have the same layout.
|
||||||
|
resource: unsafe { std::mem::transmute(S::obtain(resource)) },
|
||||||
descriptor: srv,
|
descriptor: srv,
|
||||||
size,
|
size,
|
||||||
format,
|
format,
|
||||||
wrap_mode,
|
wrap_mode,
|
||||||
filter,
|
filter,
|
||||||
|
drop_flag: S::NEEDS_CLEANUP,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,12 +132,42 @@ impl InputTexture {
|
||||||
) -> InputTexture {
|
) -> InputTexture {
|
||||||
let desc = unsafe { image.resource.GetDesc() };
|
let desc = unsafe { image.resource.GetDesc() };
|
||||||
InputTexture {
|
InputTexture {
|
||||||
resource: image.resource,
|
resource: ManuallyDrop::new(image.resource.clone()),
|
||||||
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 {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
// ensure lifetime for raw resources or if there is a drop flag
|
||||||
|
if self.descriptor.is_raw() || self.drop_flag {
|
||||||
|
InputTexture {
|
||||||
|
resource: ManuallyDrop::clone(&self.resource),
|
||||||
|
descriptor: self.descriptor.clone(),
|
||||||
|
size: self.size,
|
||||||
|
format: self.format,
|
||||||
|
wrap_mode: self.wrap_mode,
|
||||||
|
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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,3 +185,11 @@ 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) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -7,8 +7,9 @@ use windows::Win32::Graphics::Direct3D::Dxc::{
|
||||||
DXC_CP_UTF8,
|
DXC_CP_UTF8,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::resource::ResourceHandleStrategy;
|
||||||
use windows::Win32::Graphics::Direct3D12::{
|
use windows::Win32::Graphics::Direct3D12::{
|
||||||
ID3D12Device, ID3D12GraphicsCommandList, ID3D12Resource, D3D12_FEATURE_DATA_FORMAT_SUPPORT,
|
ID3D12Device, ID3D12GraphicsCommandList, D3D12_FEATURE_DATA_FORMAT_SUPPORT,
|
||||||
D3D12_FEATURE_FORMAT_SUPPORT, D3D12_RESOURCE_BARRIER, D3D12_RESOURCE_BARRIER_0,
|
D3D12_FEATURE_FORMAT_SUPPORT, D3D12_RESOURCE_BARRIER, D3D12_RESOURCE_BARRIER_0,
|
||||||
D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, D3D12_RESOURCE_BARRIER_FLAG_NONE,
|
D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, D3D12_RESOURCE_BARRIER_FLAG_NONE,
|
||||||
D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, D3D12_RESOURCE_STATES,
|
D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, D3D12_RESOURCE_STATES,
|
||||||
|
@ -174,9 +175,8 @@ pub fn dxc_validate_shader(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use = "Resource Barrier must be disposed"]
|
pub fn d3d12_get_resource_transition_subresource<S: ResourceHandleStrategy<T>, T>(
|
||||||
pub fn d3d12_get_resource_transition_subresource(
|
resource: &T,
|
||||||
resource: &ID3D12Resource,
|
|
||||||
before: D3D12_RESOURCE_STATES,
|
before: D3D12_RESOURCE_STATES,
|
||||||
after: D3D12_RESOURCE_STATES,
|
after: D3D12_RESOURCE_STATES,
|
||||||
subresource: u32,
|
subresource: u32,
|
||||||
|
@ -186,7 +186,7 @@ pub fn d3d12_get_resource_transition_subresource(
|
||||||
Flags: D3D12_RESOURCE_BARRIER_FLAG_NONE,
|
Flags: D3D12_RESOURCE_BARRIER_FLAG_NONE,
|
||||||
Anonymous: D3D12_RESOURCE_BARRIER_0 {
|
Anonymous: D3D12_RESOURCE_BARRIER_0 {
|
||||||
Transition: ManuallyDrop::new(D3D12_RESOURCE_TRANSITION_BARRIER {
|
Transition: ManuallyDrop::new(D3D12_RESOURCE_TRANSITION_BARRIER {
|
||||||
pResource: ManuallyDrop::new(Some(resource.clone())),
|
pResource: unsafe { S::obtain(resource) },
|
||||||
Subresource: subresource,
|
Subresource: subresource,
|
||||||
StateBefore: before,
|
StateBefore: before,
|
||||||
StateAfter: after,
|
StateAfter: after,
|
||||||
|
@ -195,15 +195,14 @@ pub fn d3d12_get_resource_transition_subresource(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use = "Resource Barrier must be disposed"]
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn d3d12_resource_transition(
|
pub fn d3d12_resource_transition<S: ResourceHandleStrategy<T>, T>(
|
||||||
cmd: &ID3D12GraphicsCommandList,
|
cmd: &ID3D12GraphicsCommandList,
|
||||||
resource: &ID3D12Resource,
|
resource: &T,
|
||||||
before: D3D12_RESOURCE_STATES,
|
before: D3D12_RESOURCE_STATES,
|
||||||
after: D3D12_RESOURCE_STATES,
|
after: D3D12_RESOURCE_STATES,
|
||||||
) -> [D3D12_RESOURCE_BARRIER; 1] {
|
) -> [D3D12_RESOURCE_BARRIER; 1] {
|
||||||
d3d12_resource_transition_subresource(
|
d3d12_resource_transition_subresource::<S, T>(
|
||||||
cmd,
|
cmd,
|
||||||
resource,
|
resource,
|
||||||
before,
|
before,
|
||||||
|
@ -214,14 +213,14 @@ pub fn d3d12_resource_transition(
|
||||||
|
|
||||||
#[must_use = "Resource Barrier must be disposed"]
|
#[must_use = "Resource Barrier must be disposed"]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn d3d12_resource_transition_subresource(
|
fn d3d12_resource_transition_subresource<S: ResourceHandleStrategy<T>, T>(
|
||||||
cmd: &ID3D12GraphicsCommandList,
|
cmd: &ID3D12GraphicsCommandList,
|
||||||
resource: &ID3D12Resource,
|
resource: &T,
|
||||||
before: D3D12_RESOURCE_STATES,
|
before: D3D12_RESOURCE_STATES,
|
||||||
after: D3D12_RESOURCE_STATES,
|
after: D3D12_RESOURCE_STATES,
|
||||||
subresource: u32,
|
subresource: u32,
|
||||||
) -> [D3D12_RESOURCE_BARRIER; 1] {
|
) -> [D3D12_RESOURCE_BARRIER; 1] {
|
||||||
let barrier = [d3d12_get_resource_transition_subresource(
|
let barrier = [d3d12_get_resource_transition_subresource::<S, T>(
|
||||||
resource,
|
resource,
|
||||||
before,
|
before,
|
||||||
after,
|
after,
|
||||||
|
|
|
@ -188,7 +188,7 @@ fn get_hardware_adapter(factory: &IDXGIFactory4) -> Result<IDXGIAdapter1> {
|
||||||
for i in 0.. {
|
for i in 0.. {
|
||||||
let adapter = unsafe { factory.EnumAdapters1(i)? };
|
let adapter = unsafe { factory.EnumAdapters1(i)? };
|
||||||
|
|
||||||
let mut desc = unsafe { adapter.GetDesc1()? };
|
let desc = unsafe { adapter.GetDesc1()? };
|
||||||
|
|
||||||
if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE.0 as u32) != DXGI_ADAPTER_FLAG_NONE.0 as u32 {
|
if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE.0 as u32) != DXGI_ADAPTER_FLAG_NONE.0 as u32 {
|
||||||
// Don't select the Basic Render Driver adapter. If you want a
|
// Don't select the Basic Render Driver adapter. If you want a
|
||||||
|
|
|
@ -5,8 +5,8 @@ use crate::hello_triangle::{DXSample, SampleCommandLine};
|
||||||
#[test]
|
#[test]
|
||||||
fn triangle_d3d12() {
|
fn triangle_d3d12() {
|
||||||
let sample = hello_triangle::d3d12_hello_triangle::Sample::new(
|
let sample = hello_triangle::d3d12_hello_triangle::Sample::new(
|
||||||
// "../test/shaders_slang/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp",
|
"../test/shaders_slang/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp",
|
||||||
"../test/shaders_slang/crt/crt-royale.slangp",
|
// "../test/shaders_slang/crt/crt-royale.slangp",
|
||||||
// "../test/basic.slangp",
|
// "../test/basic.slangp",
|
||||||
// "../test/shaders_slang/handheld/console-border/gbc-lcd-grid-v2.slangp",
|
// "../test/shaders_slang/handheld/console-border/gbc-lcd-grid-v2.slangp",
|
||||||
// "../test/Mega_Bezel_Packs/Duimon-Mega-Bezel/Presets/Advanced/Nintendo_GBA_SP/GBA_SP-[ADV]-[LCD-GRID]-[Night].slangp",
|
// "../test/Mega_Bezel_Packs/Duimon-Mega-Bezel/Presets/Advanced/Nintendo_GBA_SP/GBA_SP-[ADV]-[LCD-GRID]-[Night].slangp",
|
||||||
|
|
Loading…
Reference in a new issue