Skip to content

Commit aa6be88

Browse files
committed
Uses MTLResidencySet for TLAS dependencies.
1 parent a201c51 commit aa6be88

File tree

3 files changed

+86
-24
lines changed

3 files changed

+86
-24
lines changed

wgpu-hal/src/metal/command.rs

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use hashbrown::HashSet;
12
use objc2::{
23
rc::{autoreleasepool, Retained},
34
runtime::ProtocolObject,
@@ -7,8 +8,8 @@ use objc2_metal::{
78
MTLAccelerationStructureCommandEncoder, MTLBlitCommandEncoder, MTLBlitPassDescriptor,
89
MTLCommandBuffer, MTLCommandEncoder, MTLCommandQueue, MTLComputeCommandEncoder,
910
MTLComputePassDescriptor, MTLCounterDontSample, MTLLoadAction, MTLPrimitiveType,
10-
MTLRenderCommandEncoder, MTLRenderPassDescriptor, MTLScissorRect, MTLSize, MTLStoreAction,
11-
MTLTexture, MTLViewport, MTLVisibilityResultMode,
11+
MTLRenderCommandEncoder, MTLRenderPassDescriptor, MTLResidencySet, MTLScissorRect, MTLSize,
12+
MTLStoreAction, MTLTexture, MTLViewport, MTLVisibilityResultMode,
1213
};
1314

1415
use super::{conv, TimestampQuerySupport};
@@ -37,6 +38,7 @@ impl Default for super::CommandState {
3738
height: 0,
3839
},
3940
stage_infos: Default::default(),
41+
residency_sets: Default::default(),
4042
storage_buffer_length_map: Default::default(),
4143
vertex_buffer_size_map: Default::default(),
4244
work_group_memory_sizes: Vec::new(),
@@ -284,8 +286,11 @@ impl crate::CommandEncoder for super::CommandEncoder {
284286
debug_assert!(self.state.compute.is_none());
285287
debug_assert!(self.state.pending_timer_queries.is_empty());
286288

289+
let mut residency_sets = HashSet::new();
290+
core::mem::swap(&mut residency_sets, &mut self.state.residency_sets);
287291
Ok(super::CommandBuffer {
288292
raw: self.raw_cmd_buf.take().unwrap(),
293+
residency_sets,
289294
})
290295
}
291296

@@ -455,6 +460,16 @@ impl crate::CommandEncoder for super::CommandEncoder {
455460
dst: &super::AccelerationStructure,
456461
copy: wgt::AccelerationStructureCopy,
457462
) {
463+
// Store a reference of the residency_set in the encoder state to be committed later
464+
self.state
465+
.residency_sets
466+
.insert(Retained::clone(&dst.residency_set));
467+
dst.residency_set.removeAllAllocations();
468+
let allocations = src.residency_set.allAllocations();
469+
for index in 0..allocations.count() {
470+
dst.residency_set
471+
.addAllocation(&allocations.objectAtIndex(index));
472+
}
458473
let command_encoder = self.enter_acceleration_structure_builder();
459474
match copy {
460475
wgt::AccelerationStructureCopy::Clone => {
@@ -773,11 +788,12 @@ impl crate::CommandEncoder for super::CommandEncoder {
773788
changes_sizes_buffer = true;
774789
}
775790
}
776-
super::BufferLikeResource::AccelerationStructure(ptr) => {
791+
super::BufferLikeResource::AccelerationStructure(ptr, residency_set) => {
777792
encoder.setVertexAccelerationStructure_atBufferIndex(
778793
Some(ptr.as_ref()),
779794
(bg_info.base_resource_indices.vs.buffers + index) as usize,
780795
);
796+
residency_set.as_ref().requestResidency();
781797
}
782798
}
783799
}
@@ -822,11 +838,12 @@ impl crate::CommandEncoder for super::CommandEncoder {
822838
changes_sizes_buffer = true;
823839
}
824840
}
825-
super::BufferLikeResource::AccelerationStructure(ptr) => {
841+
super::BufferLikeResource::AccelerationStructure(ptr, residency_set) => {
826842
encoder.setFragmentAccelerationStructure_atBufferIndex(
827843
Some(ptr.as_ref()),
828844
(bg_info.base_resource_indices.fs.buffers + index) as usize,
829845
);
846+
residency_set.as_ref().requestResidency();
830847
}
831848
}
832849
}
@@ -914,11 +931,12 @@ impl crate::CommandEncoder for super::CommandEncoder {
914931
changes_sizes_buffer = true;
915932
}
916933
}
917-
super::BufferLikeResource::AccelerationStructure(ptr) => {
934+
super::BufferLikeResource::AccelerationStructure(ptr, residency_set) => {
918935
encoder.setAccelerationStructure_atBufferIndex(
919936
Some(ptr.as_ref()),
920937
(bg_info.base_resource_indices.cs.buffers + index) as usize,
921938
);
939+
residency_set.as_ref().requestResidency();
922940
}
923941
}
924942
}
@@ -1479,6 +1497,25 @@ impl crate::CommandEncoder for super::CommandEncoder {
14791497
for descriptor in descriptors {
14801498
let acceleration_structure_descriptor =
14811499
conv::map_acceleration_structure_descriptor(descriptor.entries, descriptor.flags);
1500+
if matches!(
1501+
descriptor.entries,
1502+
crate::AccelerationStructureEntries::Instances(_)
1503+
) {
1504+
// Store a reference of the residency_set in the encoder state to be committed later
1505+
self.state.residency_sets.insert(Retained::clone(
1506+
&descriptor.destination_acceleration_structure.residency_set,
1507+
));
1508+
descriptor
1509+
.destination_acceleration_structure
1510+
.residency_set
1511+
.removeAllAllocations();
1512+
for dependency in descriptor.dependencies.iter() {
1513+
descriptor
1514+
.destination_acceleration_structure
1515+
.residency_set
1516+
.addAllocation(dependency.raw.as_ref());
1517+
}
1518+
}
14821519
match descriptor.mode {
14831520
crate::AccelerationStructureBuildMode::Build => {
14841521
command_encoder

wgpu-hal/src/metal/device.rs

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@ use objc2_metal::{
1717
MTLDevice, MTLFunction, MTLIndirectAccelerationStructureInstanceDescriptor, MTLLanguageVersion,
1818
MTLLibrary, MTLMutability, MTLPackedFloat3, MTLPackedFloat4x3,
1919
MTLPipelineBufferDescriptorArray, MTLPixelFormat, MTLPrimitiveTopologyClass,
20-
MTLRenderPipelineDescriptor, MTLResource, MTLResourceID, MTLResourceOptions,
21-
MTLSamplerAddressMode, MTLSamplerDescriptor, MTLSamplerMipFilter, MTLSamplerState, MTLSize,
22-
MTLStencilDescriptor, MTLStorageMode, MTLTexture, MTLTextureDescriptor, MTLTextureType,
23-
MTLTriangleFillMode, MTLVertexDescriptor, MTLVertexStepFunction,
20+
MTLRenderPipelineDescriptor, MTLResidencySet, MTLResidencySetDescriptor, MTLResource,
21+
MTLResourceID, MTLResourceOptions, MTLSamplerAddressMode, MTLSamplerDescriptor,
22+
MTLSamplerMipFilter, MTLSamplerState, MTLSize, MTLStencilDescriptor, MTLStorageMode,
23+
MTLTexture, MTLTextureDescriptor, MTLTextureType, MTLTriangleFillMode, MTLVertexDescriptor,
24+
MTLVertexStepFunction,
2425
};
2526
use parking_lot::Mutex;
2627

@@ -948,10 +949,15 @@ impl crate::Device for super::Device {
948949
{
949950
contents[idx] = acceleration_structure.raw.gpuResourceID();
950951

951-
let use_info = bg
952-
.resources_to_use
953-
.entry(acceleration_structure.as_raw().cast())
954-
.or_default();
952+
let super::BufferLikeResource::AccelerationStructure(
953+
structure,
954+
_residency_set,
955+
) = acceleration_structure.as_raw()
956+
else {
957+
unreachable!();
958+
};
959+
let use_info =
960+
bg.resources_to_use.entry(structure.cast()).or_default();
955961
use_info.stages |= stages;
956962
use_info.uses |= uses;
957963
use_info.visible_in_compute |=
@@ -1045,11 +1051,7 @@ impl crate::Device for super::Device {
10451051
let end = start + 1;
10461052
bg.buffers.extend(
10471053
desc.acceleration_structures[start..end].iter().map(
1048-
|acceleration_structure| {
1049-
super::BufferLikeResource::AccelerationStructure(
1050-
acceleration_structure.as_raw(),
1051-
)
1052-
},
1054+
|acceleration_structure| acceleration_structure.as_raw(),
10531055
),
10541056
);
10551057
counter.buffers += 1;
@@ -1694,19 +1696,28 @@ impl crate::Device for super::Device {
16941696
// self.counters.acceleration_structures.add(1);
16951697
let device = self.shared.device.lock();
16961698
autoreleasepool(|_| {
1699+
let residency_set_descriptor = MTLResidencySetDescriptor::new();
1700+
residency_set_descriptor.setInitialCapacity(1);
16971701
Ok(super::AccelerationStructure {
16981702
raw: device
16991703
.newAccelerationStructureWithSize(descriptor.size as usize)
17001704
.ok_or(crate::DeviceError::OutOfMemory)?,
1705+
residency_set: device
1706+
.newResidencySetWithDescriptor_error(&residency_set_descriptor)
1707+
.map_err(|err| {
1708+
log::error!("Failed to create residency set: {err:?}");
1709+
crate::DeviceError::Unexpected
1710+
})?,
17011711
})
17021712
})
17031713
}
17041714

17051715
unsafe fn destroy_acceleration_structure(
17061716
&self,
1707-
_acceleration_structure: super::AccelerationStructure,
1717+
acceleration_structure: super::AccelerationStructure,
17081718
) {
17091719
// self.counters.acceleration_structures.sub(1);
1720+
acceleration_structure.residency_set.endResidency();
17101721
}
17111722

17121723
fn tlas_instance_to_bytes(&self, instance: TlasInstance) -> Vec<u8> {

wgpu-hal/src/metal/mod.rs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use core::{fmt, iter, ops, ptr::NonNull, sync::atomic};
3737

3838
use arrayvec::ArrayVec;
3939
use bitflags::bitflags;
40-
use hashbrown::HashMap;
40+
use hashbrown::{HashMap, HashSet};
4141
use naga::FastHashMap;
4242
use objc2::{
4343
rc::{autoreleasepool, Retained},
@@ -50,7 +50,7 @@ use objc2_metal::{
5050
MTLComputeCommandEncoder, MTLComputePipelineState, MTLCounterSampleBuffer, MTLCullMode,
5151
MTLDepthClipMode, MTLDepthStencilState, MTLDevice, MTLDrawable, MTLFunction, MTLIndexType,
5252
MTLLanguageVersion, MTLLibrary, MTLPrimitiveType, MTLReadWriteTextureTier,
53-
MTLRenderCommandEncoder, MTLRenderPipelineState, MTLRenderStages, MTLResource,
53+
MTLRenderCommandEncoder, MTLRenderPipelineState, MTLRenderStages, MTLResidencySet, MTLResource,
5454
MTLResourceUsage, MTLSamplerState, MTLSharedEvent, MTLSize, MTLTexture, MTLTextureType,
5555
MTLTriangleFillMode, MTLWinding,
5656
};
@@ -489,6 +489,9 @@ impl crate::Queue for Queue {
489489

490490
for cmd_buffer in command_buffers {
491491
cmd_buffer.raw.commit();
492+
for residency_set in &cmd_buffer.residency_sets {
493+
residency_set.commit();
494+
}
492495
}
493496

494497
if let Some(raw) = extra_command_buffer {
@@ -718,7 +721,10 @@ enum BufferLikeResource {
718721

719722
binding_location: u32,
720723
},
721-
AccelerationStructure(NonNull<ProtocolObject<dyn MTLAccelerationStructure>>),
724+
AccelerationStructure(
725+
NonNull<ProtocolObject<dyn MTLAccelerationStructure>>,
726+
NonNull<ProtocolObject<dyn MTLResidencySet>>,
727+
),
722728
}
723729

724730
#[derive(Debug)]
@@ -929,6 +935,7 @@ struct CommandState {
929935
index: Option<IndexState>,
930936
raw_wg_size: MTLSize,
931937
stage_infos: MultiStageData<PipelineStageInfo>,
938+
residency_sets: HashSet<Retained<ProtocolObject<dyn MTLResidencySet>>>,
932939

933940
/// Sizes of currently bound [`wgt::BufferBindingType::Storage`] buffers.
934941
///
@@ -984,6 +991,7 @@ unsafe impl Sync for CommandEncoder {}
984991
#[derive(Debug)]
985992
pub struct CommandBuffer {
986993
raw: Retained<ProtocolObject<dyn MTLCommandBuffer>>,
994+
residency_sets: HashSet<Retained<ProtocolObject<dyn MTLResidencySet>>>,
987995
}
988996

989997
impl crate::DynCommandBuffer for CommandBuffer {}
@@ -999,11 +1007,17 @@ impl crate::DynPipelineCache for PipelineCache {}
9991007
#[derive(Debug)]
10001008
pub struct AccelerationStructure {
10011009
raw: Retained<ProtocolObject<dyn MTLAccelerationStructure>>,
1010+
residency_set: Retained<ProtocolObject<dyn MTLResidencySet>>,
10021011
}
10031012

10041013
impl AccelerationStructure {
1005-
fn as_raw(&self) -> NonNull<ProtocolObject<dyn MTLAccelerationStructure>> {
1006-
unsafe { NonNull::new_unchecked(Retained::as_ptr(&self.raw) as *mut _) }
1014+
fn as_raw(&self) -> BufferLikeResource {
1015+
unsafe {
1016+
BufferLikeResource::AccelerationStructure(
1017+
NonNull::new_unchecked(Retained::as_ptr(&self.raw) as *mut _),
1018+
NonNull::new_unchecked(Retained::as_ptr(&self.residency_set) as *mut _),
1019+
)
1020+
}
10071021
}
10081022
}
10091023

0 commit comments

Comments
 (0)