Skip to content

Commit c57e502

Browse files
committed
rt(d3d12): make images with OwnedFramebuffer provenance use ManuallyDrop
1 parent 7edff0a commit c57e502

File tree

9 files changed

+233
-138
lines changed

9 files changed

+233
-138
lines changed

librashader-runtime-d3d12/src/filter_chain.rs

+49-41
Original file line numberDiff line numberDiff line change
@@ -131,13 +131,18 @@ impl FrameResiduals {
131131
self.mipmaps.extend(handles)
132132
}
133133

134-
pub fn dispose_resource(&mut self, resource: ManuallyDrop<Option<ID3D12Resource>>) {
134+
pub unsafe fn dispose_resource(&mut self, resource: ManuallyDrop<Option<ID3D12Resource>>) {
135135
self.resources.push(resource)
136136
}
137137

138-
/// Disposition only handles transition barriers, but it is not unsafe because
139-
/// other things just leak and leakign is not unsafe,
140-
pub fn dispose_barriers(&mut self, barrier: impl IntoIterator<Item = D3D12_RESOURCE_BARRIER>) {
138+
/// Disposition only handles transition barriers.
139+
///
140+
/// **Safety:** It is only safe to dispose a barrier created with resource strategy IncrementRef.
141+
///
142+
pub unsafe fn dispose_barriers(
143+
&mut self,
144+
barrier: impl IntoIterator<Item = D3D12_RESOURCE_BARRIER>,
145+
) {
141146
self.resource_barriers.extend(barrier);
142147
}
143148

@@ -230,6 +235,7 @@ mod compile {
230235
}
231236
}
232237

238+
use crate::resource::OutlivesFrame;
233239
use compile::{compile_passes_dxil, compile_passes_hlsl, DxilShaderPassMeta, HlslShaderPassMeta};
234240
use librashader_runtime::parameters::RuntimeParameters;
235241

@@ -321,7 +327,8 @@ impl FilterChainD3D12 {
321327
let mut staging_heap = unsafe {
322328
D3D12DescriptorHeap::new(
323329
device,
324-
(MAX_BINDINGS_COUNT as usize) * shader_count
330+
// add one, because technically the input image doesn't need to count
331+
(1 + MAX_BINDINGS_COUNT as usize) * shader_count
325332
+ MIPMAP_RESERVED_WORKHEAP_DESCRIPTORS
326333
+ lut_count,
327334
)
@@ -391,7 +398,7 @@ impl FilterChainD3D12 {
391398
common: FilterCommon {
392399
d3d12: device.clone(),
393400
samplers,
394-
allocator: allocator,
401+
allocator,
395402
output_textures,
396403
feedback_textures,
397404
luts,
@@ -460,7 +467,10 @@ impl FilterChainD3D12 {
460467

461468
gc.dispose_mipmap_handles(residual_mipmap);
462469
gc.dispose_mipmap_gen(mipmap_gen);
463-
gc.dispose_barriers(residual_barrier);
470+
471+
unsafe {
472+
gc.dispose_barriers(residual_barrier);
473+
}
464474

465475
Ok(luts)
466476
}
@@ -653,7 +663,7 @@ impl FilterChainD3D12 {
653663
);
654664
}
655665
unsafe {
656-
back.copy_from(cmd, input, &mut self.residuals)?;
666+
back.copy_from(cmd, input)?;
657667
}
658668
self.history_framebuffers.push_front(back);
659669
}
@@ -669,6 +679,8 @@ impl FilterChainD3D12 {
669679
/// librashader **will not** create a resource barrier for the final pass. The output image will
670680
/// remain in `D3D12_RESOURCE_STATE_RENDER_TARGET` after all shader passes. The caller must transition
671681
/// the output image to the final resource state.
682+
///
683+
/// The input and output images must stay alive until the command list is submitted and work is complete.
672684
pub unsafe fn frame(
673685
&mut self,
674686
cmd: &ID3D12GraphicsCommandList,
@@ -689,7 +701,7 @@ impl FilterChainD3D12 {
689701
if let Some(options) = options {
690702
if options.clear_history {
691703
for framebuffer in &mut self.history_framebuffers {
692-
framebuffer.clear(cmd, &mut self.rtv_heap, &mut self.residuals)?;
704+
framebuffer.clear(cmd, &mut self.rtv_heap)?;
693705
}
694706
}
695707
}
@@ -787,13 +799,12 @@ impl FilterChainD3D12 {
787799
)?;
788800
}
789801

790-
self.residuals
791-
.dispose_barriers(util::d3d12_resource_transition(
792-
cmd,
793-
&target.handle.resource(),
794-
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
795-
D3D12_RESOURCE_STATE_RENDER_TARGET,
796-
));
802+
util::d3d12_resource_transition::<OutlivesFrame, _>(
803+
cmd,
804+
&target.resource,
805+
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
806+
D3D12_RESOURCE_STATE_RENDER_TARGET,
807+
);
797808

798809
let view = target.create_render_target_view(&mut self.rtv_heap)?;
799810
let out = RenderTarget::identity(&view)?;
@@ -811,21 +822,21 @@ impl FilterChainD3D12 {
811822
QuadType::Offscreen,
812823
)?;
813824

814-
self.residuals
815-
.dispose_barriers(util::d3d12_resource_transition(
816-
cmd,
817-
&target.handle.resource(),
818-
D3D12_RESOURCE_STATE_RENDER_TARGET,
819-
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
820-
));
825+
util::d3d12_resource_transition::<OutlivesFrame, _>(
826+
cmd,
827+
&target.resource,
828+
D3D12_RESOURCE_STATE_RENDER_TARGET,
829+
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
830+
);
821831

822832
if target.max_mipmap > 1 && !self.disable_mipmaps {
823-
let (residuals, residual_barriers) = self.common.mipmap_gen.mipmapping_context(
833+
// barriers don't get disposed because the context is OutlivesFrame
834+
let (residuals, _residual_barriers) = self.common.mipmap_gen.mipmapping_context(
824835
cmd,
825836
&mut self.mipmap_heap,
826837
|ctx| {
827-
ctx.generate_mipmaps(
828-
&target.handle.resource(),
838+
ctx.generate_mipmaps::<OutlivesFrame, _>(
839+
&target.resource,
829840
target.max_mipmap,
830841
target.size,
831842
target.format.into(),
@@ -835,7 +846,6 @@ impl FilterChainD3D12 {
835846
)?;
836847

837848
self.residuals.dispose_mipmap_handles(residuals);
838-
self.residuals.dispose_barriers(residual_barriers);
839849
}
840850

841851
self.residuals.dispose_output(view.descriptor);
@@ -862,13 +872,12 @@ impl FilterChainD3D12 {
862872
)?;
863873
}
864874

865-
self.residuals
866-
.dispose_barriers(util::d3d12_resource_transition(
867-
cmd,
868-
&feedback_target.handle.resource(),
869-
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
870-
D3D12_RESOURCE_STATE_RENDER_TARGET,
871-
));
875+
util::d3d12_resource_transition::<OutlivesFrame, _>(
876+
cmd,
877+
&feedback_target.resource,
878+
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
879+
D3D12_RESOURCE_STATE_RENDER_TARGET,
880+
);
872881

873882
let view = feedback_target.create_render_target_view(&mut self.rtv_heap)?;
874883
let out = RenderTarget::viewport_with_output(&view, viewport);
@@ -885,13 +894,12 @@ impl FilterChainD3D12 {
885894
QuadType::Final,
886895
)?;
887896

888-
self.residuals
889-
.dispose_barriers(util::d3d12_resource_transition(
890-
cmd,
891-
&feedback_target.handle.resource(),
892-
D3D12_RESOURCE_STATE_RENDER_TARGET,
893-
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
894-
));
897+
util::d3d12_resource_transition::<OutlivesFrame, _>(
898+
cmd,
899+
&feedback_target.resource,
900+
D3D12_RESOURCE_STATE_RENDER_TARGET,
901+
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
902+
);
895903
}
896904

897905
if pass.pipeline.format != viewport.output.format {

librashader-runtime-d3d12/src/framebuffer.rs

+43-41
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::descriptor_heap::{CpuStagingHeap, RenderTargetHeap};
22
use crate::error::FilterChainError;
3-
use crate::filter_chain::FrameResiduals;
3+
use crate::resource::{OutlivesFrame, ResourceHandleStrategy};
44
use crate::texture::{D3D12OutputView, InputTexture};
55
use crate::util::d3d12_get_closest_format;
66
use crate::{error, util};
@@ -17,12 +17,13 @@ use parking_lot::Mutex;
1717
use std::mem::ManuallyDrop;
1818
use std::sync::Arc;
1919
use windows::Win32::Graphics::Direct3D12::{
20-
ID3D12Device, ID3D12GraphicsCommandList, D3D12_BOX, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
21-
D3D12_FEATURE_DATA_FORMAT_SUPPORT, D3D12_FORMAT_SUPPORT1_MIP,
22-
D3D12_FORMAT_SUPPORT1_RENDER_TARGET, D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE,
23-
D3D12_FORMAT_SUPPORT1_TEXTURE2D, D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD,
24-
D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE, D3D12_RENDER_TARGET_VIEW_DESC,
25-
D3D12_RENDER_TARGET_VIEW_DESC_0, D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, D3D12_RESOURCE_DESC,
20+
ID3D12Device, ID3D12GraphicsCommandList, ID3D12Resource, D3D12_BOX,
21+
D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING, D3D12_FEATURE_DATA_FORMAT_SUPPORT,
22+
D3D12_FORMAT_SUPPORT1_MIP, D3D12_FORMAT_SUPPORT1_RENDER_TARGET,
23+
D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE, D3D12_FORMAT_SUPPORT1_TEXTURE2D,
24+
D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD, D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE,
25+
D3D12_RENDER_TARGET_VIEW_DESC, D3D12_RENDER_TARGET_VIEW_DESC_0,
26+
D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, D3D12_RESOURCE_DESC,
2627
D3D12_RESOURCE_DIMENSION_TEXTURE2D, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET,
2728
D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_DEST,
2829
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};
3637
#[derive(Debug)]
3738
pub(crate) struct OwnedImage {
3839
pub(crate) handle: ManuallyDrop<Resource>,
40+
pub(crate) resource: ManuallyDrop<ID3D12Resource>,
3941
pub(crate) size: Size<u32>,
4042
pub(crate) format: DXGI_FORMAT,
4143
pub(crate) max_mipmap: u16,
@@ -113,7 +115,7 @@ impl OwnedImage {
113115

114116
desc.Format = d3d12_get_closest_format(device, format_support);
115117

116-
let resource = allocator.lock().create_resource(&ResourceCreateDesc {
118+
let allocator_resource = allocator.lock().create_resource(&ResourceCreateDesc {
117119
name: "ownedimage",
118120
memory_location: MemoryLocation::GpuOnly,
119121
resource_category: ResourceCategory::RtvDsvTexture,
@@ -145,8 +147,10 @@ impl OwnedImage {
145147
// }
146148
// assume_d3d12_init!(resource, "CreateCommittedResource");
147149

150+
let resource = ManuallyDrop::new(allocator_resource.resource().clone());
148151
Ok(OwnedImage {
149-
handle: ManuallyDrop::new(resource),
152+
handle: ManuallyDrop::new(allocator_resource),
153+
resource,
150154
size,
151155
format: desc.Format,
152156
device: device.clone(),
@@ -161,17 +165,16 @@ impl OwnedImage {
161165
&self,
162166
cmd: &ID3D12GraphicsCommandList,
163167
input: &InputTexture,
164-
gc: &mut FrameResiduals,
165168
) -> error::Result<()> {
166169
let barriers = [
167-
util::d3d12_get_resource_transition_subresource(
170+
util::d3d12_get_resource_transition_subresource::<OutlivesFrame, _>(
168171
&input.resource,
169172
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
170173
D3D12_RESOURCE_STATE_COPY_SOURCE,
171174
D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
172175
),
173-
util::d3d12_get_resource_transition_subresource(
174-
&self.handle.resource(),
176+
util::d3d12_get_resource_transition_subresource::<OutlivesFrame, _>(
177+
&self.resource,
175178
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
176179
D3D12_RESOURCE_STATE_COPY_DEST,
177180
D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
@@ -180,18 +183,17 @@ impl OwnedImage {
180183

181184
unsafe {
182185
cmd.ResourceBarrier(&barriers);
183-
gc.dispose_barriers(barriers);
184186

185187
let dst = D3D12_TEXTURE_COPY_LOCATION {
186-
pResource: ManuallyDrop::new(Some(self.handle.resource().clone())),
188+
pResource: OutlivesFrame::obtain(&self.resource),
187189
Type: D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
188190
Anonymous: D3D12_TEXTURE_COPY_LOCATION_0 {
189191
SubresourceIndex: 0,
190192
},
191193
};
192194

193195
let src = D3D12_TEXTURE_COPY_LOCATION {
194-
pResource: ManuallyDrop::new(Some(input.resource.clone())),
196+
pResource: OutlivesFrame::obtain(&input.resource),
195197
Type: D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
196198
Anonymous: D3D12_TEXTURE_COPY_LOCATION_0 {
197199
SubresourceIndex: 0,
@@ -213,20 +215,17 @@ impl OwnedImage {
213215
back: 1,
214216
}),
215217
);
216-
217-
gc.dispose_resource(dst.pResource);
218-
gc.dispose_resource(src.pResource);
219218
}
220219

221220
let barriers = [
222-
util::d3d12_get_resource_transition_subresource(
221+
util::d3d12_get_resource_transition_subresource::<OutlivesFrame, _>(
223222
&input.resource,
224223
D3D12_RESOURCE_STATE_COPY_SOURCE,
225224
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
226225
D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
227226
),
228-
util::d3d12_get_resource_transition_subresource(
229-
&self.handle.resource(),
227+
util::d3d12_get_resource_transition_subresource::<OutlivesFrame, _>(
228+
&self.resource,
230229
D3D12_RESOURCE_STATE_COPY_DEST,
231230
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
232231
D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
@@ -237,34 +236,33 @@ impl OwnedImage {
237236
cmd.ResourceBarrier(&barriers);
238237
}
239238

240-
gc.dispose_barriers(barriers);
241-
242239
Ok(())
243240
}
244241

245242
pub fn clear(
246243
&self,
247244
cmd: &ID3D12GraphicsCommandList,
248245
heap: &mut D3D12DescriptorHeap<RenderTargetHeap>,
249-
gc: &mut FrameResiduals,
250246
) -> error::Result<()> {
251-
gc.dispose_barriers(util::d3d12_resource_transition(
252-
cmd,
253-
&self.handle.resource(),
254-
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
255-
D3D12_RESOURCE_STATE_RENDER_TARGET,
256-
));
247+
unsafe {
248+
util::d3d12_resource_transition::<OutlivesFrame, _>(
249+
cmd,
250+
&self.resource,
251+
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
252+
D3D12_RESOURCE_STATE_RENDER_TARGET,
253+
);
257254

258-
let rtv = self.create_render_target_view(heap)?;
255+
let rtv = self.create_render_target_view(heap)?;
259256

260-
unsafe { cmd.ClearRenderTargetView(*rtv.descriptor.as_ref(), CLEAR, None) }
257+
cmd.ClearRenderTargetView(*rtv.descriptor.as_ref(), CLEAR, None);
261258

262-
gc.dispose_barriers(util::d3d12_resource_transition(
263-
cmd,
264-
&self.handle.resource(),
265-
D3D12_RESOURCE_STATE_RENDER_TARGET,
266-
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
267-
));
259+
util::d3d12_resource_transition::<OutlivesFrame, _>(
260+
cmd,
261+
&self.resource,
262+
D3D12_RESOURCE_STATE_RENDER_TARGET,
263+
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
264+
);
265+
}
268266

269267
Ok(())
270268
}
@@ -297,8 +295,8 @@ impl OwnedImage {
297295
);
298296
}
299297

300-
Ok(InputTexture::new(
301-
self.handle.resource().clone(),
298+
Ok(InputTexture::new::<OutlivesFrame, _>(
299+
&self.resource,
302300
descriptor,
303301
self.size,
304302
self.format,
@@ -390,6 +388,10 @@ impl ScaleFramebuffer for OwnedImage {
390388

391389
impl Drop for OwnedImage {
392390
fn drop(&mut self) {
391+
// let go of the handle
392+
unsafe {
393+
ManuallyDrop::drop(&mut self.resource);
394+
}
393395
let resource = unsafe { ManuallyDrop::take(&mut self.handle) };
394396
if let Err(e) = self.allocator.lock().free_resource(resource) {
395397
println!("librashader-runtime-d3d12: [warn] failed to deallocate owned image buffer memory {e}")

0 commit comments

Comments
 (0)